Repository: knative/serving
Pull request #9100 (2020-08-19 02:06:32)

Add short domains to ingress.spec.rules.hosts for cluster local visibility
**Proposed Changes**

This patch expands host names to short names in
ingress.rules.hosts. For example,
`hello-example.default.svc.cluster.local` will have
`hello-example.default.svc` and `hello-example.default`.

* Ingress after this patch:
```
  spec:
    rules:
    - hosts:
      - hello-example.default.svc.cluster.local
      - hello-example.default.svc
      - hello-example.default
      http:
        paths:
        - splits:
          - appendHeaders:
              Knative-Serving-Namespace: default
              Knative-Serving-Revision: hello-example-fsjyh-1
            percent: 100
            serviceName: hello-example-fsjyh-1
            serviceNamespace: default
            servicePort: 80
          timeout: 48h0m0s
      visibility: ClusterLocal
```

Currently each KIngress has to expand the host names by themselves, but
Knative Ingress should have the host names in the rules to make it easy.
Actually I got the exact same question [here](https://github.com/Kong/kubernetes-ingress-controller/pull/804#issuecomment-675775423).

**Release Note**

```release-note
Ingress objects have short names in the spec.rules.hosts for ClusterLocal visibility.
```

/lint


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

This pull-request has been approved by: *<a href="https://github.com/knative/serving/pull/9100#" title="Author self-approved">nak3</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/reconciler/route/OWNERS](https://github.com/knative/serving/blob/master/pkg/reconciler/route/OWNERS)~~ [nak3]

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":[]} -->
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/route/resources/ingress.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-go-coverage/1295905240020684800/artifacts/line-cov.html#file0) | 98.6% | 98.8% | 0.2

ZhiminXiang: cc @mattmoor 
I am not sure if this PR has any impact on contour when handling cluster local ksvc.
nak3: /cc @tcnghia @ZhiminXiang @mattmoor @hbagdi @jmprusi 

I think it makes easier to implement KIngress conformant, but WDYT?
knative-prow-robot: @nak3: GitHub didn't allow me to request PR reviews from the following users: hbagdi.

Note that only [knative members](https://github.com/orgs/knative/people) and repo collaborators can review this PR, and authors cannot review their own PRs.

<details>

In response to [this](https://github.com/knative/serving/pull/9100#issuecomment-675815121):

>/cc @tcnghia @ZhiminXiang @mattmoor @hbagdi @jmprusi 
>
>I think it makes easier to implement KIngress conformant, but WDYT?


Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository.
</details>
nak3: /test all
knative-metrics-robot: The following is the coverage report on the affected files.
Say `/test pull-knative-serving-go-coverage` to re-run this coverage report

File | Old Coverage | New Coverage | Delta
---- |:------------:|:------------:|:-----:
[pkg/reconciler/route/resources/ingress.go](https://storage.cloud.google.com/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-go-coverage/1295924995884584969/artifacts/line-cov.html#file0) | 98.6% | 98.8% | 0.2

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`
pull-knative-serving-istio-latest-no-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-no-mesh/1295924995884584967) | `/test pull-knative-serving-istio-latest-no-mesh`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`
pull-knative-serving-istio-latest-no-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-no-mesh/1295924995884584967) | `/test pull-knative-serving-istio-latest-no-mesh`
pull-knative-serving-https | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-https/1295924995888779266) | `/test pull-knative-serving-https`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`
pull-knative-serving-istio-latest-no-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-no-mesh/1295924995884584967) | `/test pull-knative-serving-istio-latest-no-mesh`
pull-knative-serving-https | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-https/1295924995888779266) | `/test pull-knative-serving-https`
pull-knative-serving-kong-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kong-latest/1295924995884584972) | `/test pull-knative-serving-kong-latest`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`
pull-knative-serving-istio-latest-no-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-no-mesh/1295924995884584967) | `/test pull-knative-serving-istio-latest-no-mesh`
pull-knative-serving-https | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-https/1295924995888779266) | `/test pull-knative-serving-https`
pull-knative-serving-kong-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kong-latest/1295924995884584972) | `/test pull-knative-serving-kong-latest`
pull-knative-serving-ambassador-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-ambassador-latest/1295924995888779264) | `/test pull-knative-serving-ambassador-latest`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`
pull-knative-serving-istio-latest-no-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-no-mesh/1295924995884584967) | `/test pull-knative-serving-istio-latest-no-mesh`
pull-knative-serving-https | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-https/1295924995888779266) | `/test pull-knative-serving-https`
pull-knative-serving-kong-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kong-latest/1295924995884584972) | `/test pull-knative-serving-kong-latest`
pull-knative-serving-ambassador-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-ambassador-latest/1295924995888779264) | `/test pull-knative-serving-ambassador-latest`
pull-knative-serving-istio-latest-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-mesh/1295924995884584960) | `/test pull-knative-serving-istio-latest-mesh`

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

<details>

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

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-knative-serving-kourier-stable | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kourier-stable/1295924995884584961) | `/test pull-knative-serving-kourier-stable`
pull-knative-serving-build-tests | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-build-tests/1295924995884584962) | `/test pull-knative-serving-build-tests`
pull-knative-serving-istio-stable-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-stable-mesh/1295924995884584964) | `/test pull-knative-serving-istio-stable-mesh`
pull-knative-serving-istio-latest-no-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-no-mesh/1295924995884584967) | `/test pull-knative-serving-istio-latest-no-mesh`
pull-knative-serving-https | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-https/1295924995888779266) | `/test pull-knative-serving-https`
pull-knative-serving-kong-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-kong-latest/1295924995884584972) | `/test pull-knative-serving-kong-latest`
pull-knative-serving-ambassador-latest | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-ambassador-latest/1295924995888779264) | `/test pull-knative-serving-ambassador-latest`
pull-knative-serving-istio-latest-mesh | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-istio-latest-mesh/1295924995884584960) | `/test pull-knative-serving-istio-latest-mesh`
pull-knative-serving-gloo-0.17.1 | 63456536141e27ce065eb90f074afbfd15251636 | [link](https://prow.knative.dev/view/gs/knative-prow/pr-logs/pull/knative_serving/9100/pull-knative-serving-gloo-0.17.1/1295924995884584968) | `/test pull-knative-serving-gloo-0.17.1`

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

<details>

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

Patch:
diff --git a/pkg/autoscaler/metrics/stats_scraper.go b/pkg/autoscaler/metrics/stats_scraper.go
index 84c95622d..048c003f2 100644
--- a/pkg/autoscaler/metrics/stats_scraper.go
+++ b/pkg/autoscaler/metrics/stats_scraper.go
@@ -23,11 +23,11 @@ import (
 	"net/http"
 	"strconv"
 	"sync"
-	"sync/atomic"
 	"time"
 
 	"go.opencensus.io/stats"
 	"go.opencensus.io/stats/view"
+	"go.uber.org/atomic"
 	"go.uber.org/zap"
 	"golang.org/x/sync/errgroup"
 
@@ -193,31 +193,34 @@ func urlFromTarget(t, ns string) string {
 
 // Scrape calls the destination service then sends it
 // to the given stats channel.
-func (s *serviceScraper) Scrape(window time.Duration) (Stat, error) {
-	readyPodsCount, err := s.podAccessor.ReadyCount()
-	if err != nil {
-		return emptyStat, ErrFailedGetEndpoints
-	}
-
-	if readyPodsCount == 0 {
-		return emptyStat, nil
-	}
-
+func (s *serviceScraper) Scrape(window time.Duration) (stat Stat, err error) {
 	startTime := time.Now()
 	defer func() {
+		// No errors and an empty stat? We didn't scrape at all because
+		// we're scaled to 0.
+		if stat == emptyStat && err == nil {
+			return
+		}
 		scrapeTime := time.Since(startTime)
 		pkgmetrics.RecordBatch(s.statsCtx, scrapeTimeM.M(float64(scrapeTime.Milliseconds())))
 	}()
 
 	if s.podsAddressable {
-		stat, err := s.scrapePods(readyPodsCount)
+		stat, err = s.scrapePods()
 		// Some pods were scraped, but not enough.
 		if err != errNoPodsScraped {
 			return stat, err
 		}
 		// Else fall back to service scrape.
 	}
-	stat, err := s.scrapeService(window, readyPodsCount)
+	readyPodsCount, err := s.podAccessor.ReadyCount()
+	if err != nil {
+		return emptyStat, ErrFailedGetEndpoints
+	}
+	if readyPodsCount == 0 {
+		return emptyStat, nil
+	}
+	stat, err = s.scrapeService(window, readyPodsCount)
 	if err == nil {
 		s.logger.Info("Direct pod scraping off, service scraping, on")
 		// If err == nil, this means that we failed to scrape all pods, but service worked
@@ -227,26 +230,23 @@ func (s *serviceScraper) Scrape(window time.Duration) (Stat, error) {
 	return stat, err
 }
 
-func (s *serviceScraper) scrapePods(readyPods int) (Stat, error) {
+func (s *serviceScraper) scrapePods() (Stat, error) {
 	pods, err := s.podAccessor.PodIPsByAge()
 	if err != nil {
 		s.logger.Info("Error querying pods by age: ", err)
 		return emptyStat, err
 	}
-	// Race condition when scaling to 0, where the check above
-	// for endpoint count worked, but here we had no ready pods.
 	if len(pods) == 0 {
-		s.logger.Infof("For %s ready pods found 0 pods, are we scaling to 0?", readyPods)
 		return emptyStat, nil
 	}
 
-	frpc := float64(readyPods)
+	frpc := float64(len(pods))
 	sampleSizeF := populationMeanSampleSize(frpc)
 	sampleSize := int(sampleSizeF)
 	results := make(chan Stat, sampleSize)
 
 	grp := errgroup.Group{}
-	idx := int32(-1)
+	idx := atomic.NewInt32(-1)
 	// Start |sampleSize| threads to scan in parallel.
 	for i := 0; i < sampleSize; i++ {
 		grp.Go(func() error {
@@ -254,7 +254,7 @@ func (s *serviceScraper) scrapePods(readyPods int) (Stat, error) {
 			// scanning pods down the line.
 			for {
 				// Acquire next pod.
-				myIdx := int(atomic.AddInt32(&idx, 1))
+				myIdx := int(idx.Inc())
 				// All out?
 				if myIdx >= len(pods) {
 					return errPodsExhausted
diff --git a/pkg/reconciler/autoscaling/kpa/kpa.go b/pkg/reconciler/autoscaling/kpa/kpa.go
index 999a1e06e..624dc0b2e 100644
--- a/pkg/reconciler/autoscaling/kpa/kpa.go
+++ b/pkg/reconciler/autoscaling/kpa/kpa.go
@@ -44,7 +44,10 @@ import (
 	corev1listers "k8s.io/client-go/listers/core/v1"
 )
 
-const noPrivateServiceName = "No Private Service Name"
+const (
+	noPrivateServiceName = "No Private Service Name"
+	noTrafficReason      = "NoTraffic"
+)
 
 // podCounts keeps record of various numbers of pods
 // for each revision.
@@ -236,7 +239,11 @@ func reportMetrics(pa *pav1alpha1.PodAutoscaler, pc podCounts) error {
 //    | -1   | >= min | >0    | active     | active     |
 func computeActiveCondition(ctx context.Context, pa *pav1alpha1.PodAutoscaler, pc podCounts) {
 	minReady := activeThreshold(ctx, pa)
-	if pc.ready >= minReady {
+	// In pre-0.17 we could have scaled down normally without ever setting ScaleTargetInitialized.
+	// In this case we'll be in the NoTraffic/inactive state.
+	// TODO(taragu): remove after 0.19
+	alreadyScaledDownSuccessfully := minReady > 0 && pa.Status.GetCondition(pav1alpha1.PodAutoscalerConditionActive).Reason == noTrafficReason
+	if pc.ready >= minReady || alreadyScaledDownSuccessfully {
 		pa.Status.MarkScaleTargetInitialized()
 	}
 
@@ -247,7 +254,7 @@ func computeActiveCondition(ctx context.Context, pa *pav1alpha1.PodAutoscaler, p
 			// We only ever scale to zero while activating if we fail to activate within the progress deadline.
 			pa.Status.MarkInactive("TimedOut", "The target could not be activated.")
 		} else {
-			pa.Status.MarkInactive("NoTraffic", "The target is not receiving traffic.")
+			pa.Status.MarkInactive(noTrafficReason, "The target is not receiving traffic.")
 		}
 
 	case pc.ready < minReady:
@@ -262,7 +269,7 @@ func computeActiveCondition(ctx context.Context, pa *pav1alpha1.PodAutoscaler, p
 			// still need to set it again. Otherwise reconciliation will fail with NewObservedGenFailure
 			// because we cannot go through one iteration of reconciliation without setting
 			// some status.
-			pa.Status.MarkInactive("NoTraffic", "The target is not receiving traffic.")
+			pa.Status.MarkInactive(noTrafficReason, "The target is not receiving traffic.")
 		}
 
 	case pc.ready >= minReady:
diff --git a/pkg/reconciler/route/resources/ingress.go b/pkg/reconciler/route/resources/ingress.go
index 9f5608462..9f8d29081 100644
--- a/pkg/reconciler/route/resources/ingress.go
+++ b/pkg/reconciler/route/resources/ingress.go
@@ -24,10 +24,12 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
+	"k8s.io/apimachinery/pkg/util/sets"
 
 	network "knative.dev/networking/pkg"
 	"knative.dev/networking/pkg/apis/networking"
 	netv1alpha1 "knative.dev/networking/pkg/apis/networking/v1alpha1"
+	ingress "knative.dev/networking/pkg/ingress"
 	"knative.dev/pkg/kmeta"
 	"knative.dev/serving/pkg/activator"
 	defaults "knative.dev/serving/pkg/apis/config"
@@ -112,11 +114,11 @@ func MakeIngressSpec(
 			visibilities = append(visibilities, netv1alpha1.IngressVisibilityExternalIP)
 		}
 		for _, visibility := range visibilities {
-			domain, err := routeDomain(ctx, name, r, visibility)
+			domains, err := routeDomain(ctx, name, r, visibility)
 			if err != nil {
 				return netv1alpha1.IngressSpec{}, err
 			}
-			rule := makeIngressRule(ctx, []string{domain}, r.Namespace, visibility, targets[name])
+			rule := makeIngressRule(ctx, domains, r.Namespace, visibility, targets[name])
 			if networkConfig.TagHeaderBasedRouting {
 				if rule.HTTP.Paths[0].AppendHeaders == nil {
 					rule.HTTP.Paths[0].AppendHeaders = make(map[string]string)
@@ -147,7 +149,7 @@ func MakeIngressSpec(
 			// If this is a public rule, we need to configure ACME challenge paths.
 			if visibility == netv1alpha1.IngressVisibilityExternalIP {
 				rule.HTTP.Paths = append(
-					makeACMEIngressPaths(challengeHosts, []string{domain}), rule.HTTP.Paths...)
+					makeACMEIngressPaths(challengeHosts, domains), rule.HTTP.Paths...)
 			}
 			rules = append(rules, rule)
 		}
@@ -169,17 +171,25 @@ func getChallengeHosts(challenges []netv1alpha1.HTTP01Challenge) map[string]netv
 	return c
 }
 
-func routeDomain(ctx context.Context, targetName string, r *servingv1.Route, visibility netv1alpha1.IngressVisibility) (string, error) {
+func routeDomain(ctx context.Context, targetName string, r *servingv1.Route, visibility netv1alpha1.IngressVisibility) ([]string, error) {
 	hostname, err := domains.HostnameFromTemplate(ctx, r.Name, targetName)
 	if err != nil {
-		return "", err
+		return []string{}, err
 	}
 
 	meta := r.ObjectMeta.DeepCopy()
 	isClusterLocal := visibility == netv1alpha1.IngressVisibilityClusterLocal
 	labels.SetVisibility(meta, isClusterLocal)
 
-	return domains.DomainNameFromTemplate(ctx, *meta, hostname)
+	domain, err := domains.DomainNameFromTemplate(ctx, *meta, hostname)
+	if err != nil {
+		return []string{}, err
+	}
+	domains := []string{domain}
+	if isClusterLocal {
+		domains = ingress.ExpandedHosts(sets.NewString(domains...)).List()
+	}
+	return domains, err
 }
 
 func makeACMEIngressPaths(challenges map[string]netv1alpha1.HTTP01Challenge, domains []string) []netv1alpha1.HTTPIngressPath {
diff --git a/third_party/cert-manager-0.12.0/net-certmanager.yaml b/third_party/cert-manager-0.12.0/net-certmanager.yaml
index 0c90223f7..def4d337e 100644
--- a/third_party/cert-manager-0.12.0/net-certmanager.yaml
+++ b/third_party/cert-manager-0.12.0/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: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
     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: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
 webhooks:
 - admissionReviewVersions:
   - v1beta1
@@ -86,7 +86,7 @@ metadata:
   name: net-certmanager-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
 
 ---
 # Copyright 2020 The Knative Authors
@@ -109,7 +109,7 @@ metadata:
   name: config-certmanager
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
     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: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
     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: "v20200818-5a44c5e"
+        serving.knative.dev/release: "v20200819-8a5392f"
     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:e54621fd5a3f968dc3f4e0514a99b26719d5bc2a7222f7ad0ae2843924c29989
+        image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/controller@sha256:8e3e77b4bf6cc2353498388cb92b28ba2c6e66c45794a59094145c366f63563e
         resources:
           requests:
             cpu: 30m
@@ -208,7 +208,7 @@ kind: Service
 metadata:
   labels:
     app: networking-certmanager
-    serving.knative.dev/release: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
     networking.knative.dev/certificate-provider: cert-manager
   name: networking-certmanager
   namespace: knative-serving
@@ -245,7 +245,7 @@ metadata:
   name: net-certmanager-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
 spec:
   selector:
     matchLabels:
@@ -258,14 +258,14 @@ spec:
       labels:
         app: net-certmanager-webhook
         role: net-certmanager-webhook
-        serving.knative.dev/release: "v20200818-5a44c5e"
+        serving.knative.dev/release: "v20200819-8a5392f"
     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:158e0a8e3799afd49733884bd3172c3effb7b3a73216fd7851f48926c996b37f
+        image: gcr.io/knative-nightly/knative.dev/net-certmanager/cmd/webhook@sha256:e705f98bc7e3594c932d14acc1088846ece6085e156173cb02e9895d8955a205
         resources:
           requests:
             cpu: 20m
@@ -319,7 +319,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: net-certmanager-webhook
-    serving.knative.dev/release: "v20200818-5a44c5e"
+    serving.knative.dev/release: "v20200819-8a5392f"
 spec:
   ports:
   - # Define metrics and profiling for them to be accessible within service meshes.
diff --git a/vendor/knative.dev/networking/pkg/ingress/doc.go b/vendor/knative.dev/networking/pkg/ingress/doc.go
new file mode 100644
index 000000000..518c77dc8
--- /dev/null
+++ b/vendor/knative.dev/networking/pkg/ingress/doc.go
@@ -0,0 +1,19 @@
+/*
+Copyright 2019 The Knative Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+// Package ingress holds utilities related to the implementation of ingress
+// controllers.
+package ingress
diff --git a/vendor/knative.dev/networking/pkg/ingress/ingress.go b/vendor/knative.dev/networking/pkg/ingress/ingress.go
new file mode 100644
index 000000000..c3fd0881d
--- /dev/null
+++ b/vendor/knative.dev/networking/pkg/ingress/ingress.go
@@ -0,0 +1,102 @@
+/*
+Copyright 2019 The Knative Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package ingress
+
+import (
+	"crypto/sha256"
+	"encoding/json"
+	"fmt"
+	"strings"
+
+	"k8s.io/apimachinery/pkg/util/sets"
+	net "knative.dev/networking/pkg"
+	"knative.dev/networking/pkg/apis/networking/v1alpha1"
+	"knative.dev/pkg/network"
+)
+
+// ComputeHash computes a hash of the Ingress Spec, Namespace and Name
+func ComputeHash(ing *v1alpha1.Ingress) ([sha256.Size]byte, error) {
+	bytes, err := json.Marshal(ing.Spec)
+	if err != nil {
+		return [sha256.Size]byte{}, fmt.Errorf("failed to serialize Ingress: %w", err)
+	}
+	bytes = append(bytes, []byte(ing.GetNamespace())...)
+	bytes = append(bytes, []byte(ing.GetName())...)
+	return sha256.Sum256(bytes), nil
+}
+
+// InsertProbe adds a AppendHeader rule so that any request going through a Gateway is tagged with
+// the version of the Ingress currently deployed on the Gateway.
+// TODO: move this to github.com/knative/networking — currently it is used by downstream
+// consumers, see: https://github.com/knative/serving/issues/7482.
+func InsertProbe(ing *v1alpha1.Ingress) (string, error) {
+	bytes, err := ComputeHash(ing)
+	if err != nil {
+		return "", fmt.Errorf("failed to compute the hash of the Ingress: %w", err)
+	}
+	hash := fmt.Sprintf("%x", bytes)
+
+	for _, rule := range ing.Spec.Rules {
+		if rule.HTTP == nil {
+			return "", fmt.Errorf("rule is missing HTTP block: %+v", rule)
+		}
+		for i := range rule.HTTP.Paths {
+			if rule.HTTP.Paths[i].AppendHeaders == nil {
+				rule.HTTP.Paths[i].AppendHeaders = make(map[string]string, 1)
+			}
+			rule.HTTP.Paths[i].AppendHeaders[net.HashHeaderName] = hash
+		}
+	}
+
+	return hash, nil
+}
+
+// HostsPerVisibility takes an Ingress and a map from visibility levels to a set of string keys,
+// it then returns a map from that key space to the hosts under that visibility.
+func HostsPerVisibility(ing *v1alpha1.Ingress, visibilityToKey map[v1alpha1.IngressVisibility]sets.String) map[string]sets.String {
+	output := make(map[string]sets.String, 2) // We currently have public and internal.
+	for _, rule := range ing.Spec.Rules {
+		for host := range ExpandedHosts(sets.NewString(rule.Hosts...)) {
+			for key := range visibilityToKey[rule.Visibility] {
+				if _, ok := output[key]; !ok {
+					output[key] = make(sets.String, len(rule.Hosts))
+				}
+				output[key].Insert(host)
+			}
+		}
+	}
+	return output
+}
+
+// ExpandedHosts sets up hosts for the short-names for cluster DNS names.
+func ExpandedHosts(hosts sets.String) sets.String {
+	allowedSuffixes := []string{
+		"",
+		"." + network.GetClusterDomainName(),
+		".svc." + network.GetClusterDomainName(),
+	}
+	// Optimistically pre-alloc.
+	expanded := make(sets.String, len(hosts)*len(allowedSuffixes))
+	for _, h := range hosts.List() {
+		for _, suffix := range allowedSuffixes {
+			if strings.HasSuffix(h, suffix) {
+				expanded.Insert(strings.TrimSuffix(h, suffix))
+			}
+		}
+	}
+	return expanded
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index eeaabe5d6..347e35deb 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1102,6 +1102,7 @@ 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/istio/listers/networking/v1alpha3
 knative.dev/networking/pkg/client/listers/networking/v1alpha1
+knative.dev/networking/pkg/ingress
 # knative.dev/pkg v0.0.0-20200812224206-44c860147a87
 ## explicit
 knative.dev/pkg/apiextensions/storageversion


Test patch:
diff --git a/pkg/autoscaler/metrics/stats_scraper_test.go b/pkg/autoscaler/metrics/stats_scraper_test.go
index 9fb2daaad..188b173e7 100644
--- a/pkg/autoscaler/metrics/stats_scraper_test.go
+++ b/pkg/autoscaler/metrics/stats_scraper_test.go
@@ -187,7 +187,6 @@ func TestPodDirectScrapeSuccess(t *testing.T) {
 		cancel()
 		wf()
 	})
-	makePods(ctx, 3)
 
 	client := newTestScrapeClient(testStats, []error{nil})
 	scraper, err := serviceScraperForTest(ctx, t, client, nil /* mesh not used */, true)
@@ -195,6 +194,14 @@ func TestPodDirectScrapeSuccess(t *testing.T) {
 		t.Fatal("serviceScraperForTest:", err)
 	}
 
+	// No pods at all.
+	if stat, err := scraper.Scrape(defaultMetric.Spec.StableWindow); err != nil {
+		t.Error("Unexpected error from scraper.Scrape():", err)
+	} else if !cmp.Equal(stat, emptyStat) {
+		t.Errorf("Wanted empty stat got: %#v", stat)
+	}
+
+	makePods(ctx, 3)
 	if _, err := scraper.Scrape(defaultMetric.Spec.StableWindow); err != nil {
 		t.Fatal("Unexpected error from scraper.Scrape():", err)
 	}
diff --git a/pkg/reconciler/autoscaling/kpa/kpa_test.go b/pkg/reconciler/autoscaling/kpa/kpa_test.go
index 6a4e87065..a2e8cac9b 100644
--- a/pkg/reconciler/autoscaling/kpa/kpa_test.go
+++ b/pkg/reconciler/autoscaling/kpa/kpa_test.go
@@ -244,8 +244,8 @@ func TestReconcile(t *testing.T) {
 
 	inactiveKPAMinScale := func(g int32) *asv1a1.PodAutoscaler {
 		return kpa(
-			testNamespace, testRevision, WithPASKSNotReady(""),
-			WithNoTraffic("NoTraffic", "The target is not receiving traffic."),
+			testNamespace, testRevision, WithPASKSNotReady(""), WithScaleTargetInitialized,
+			WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
 			withScales(g, unknownScale), WithReachabilityReachable,
 			withMinScale(defaultScale), WithPAStatusService(testRevision),
 			WithPAMetricsService(privateSvc), WithObservedGeneration(1),
@@ -438,7 +438,7 @@ func TestReconcile(t *testing.T) {
 		Name: "pa activates",
 		Key:  key,
 		Objects: []runtime.Object{
-			kpa(testNamespace, testRevision, WithNoTraffic("NoTraffic", "The target is not receiving traffic."),
+			kpa(testNamespace, testRevision, WithScaleTargetInitialized, WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
 				withScales(0, defaultScale), WithPAStatusService(testRevision), WithPAMetricsService(privateSvc)),
 			// SKS is ready here, since its endpoints are populated with Activator endpoints.
 			sks(testNamespace, testRevision, WithProxyMode, WithDeployRef(deployName), WithSKSReady),
@@ -450,7 +450,7 @@ func TestReconcile(t *testing.T) {
 				WithDeployRef(deployName)),
 		}},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: kpa(testNamespace, testRevision, WithBufferedTraffic, withScales(0, defaultScale),
+			Object: kpa(testNamespace, testRevision, WithScaleTargetInitialized, WithBufferedTraffic, withScales(0, defaultScale),
 				WithPASKSReady, WithPAMetricsService(privateSvc),
 				WithPAStatusService(testRevision), WithObservedGeneration(1)),
 		}},
@@ -677,8 +677,8 @@ func TestReconcile(t *testing.T) {
 		Ctx: context.WithValue(context.Background(), deciderKey{},
 			decider(testNamespace, testRevision, 0 /* desiredScale */, 0 /* ebc */, scaling.MinActivators)),
 		Objects: []runtime.Object{
-			kpa(testNamespace, testRevision, withScales(0, 0),
-				WithNoTraffic("NoTraffic", "The target is not receiving traffic."),
+			kpa(testNamespace, testRevision, WithScaleTargetInitialized, withScales(0, 0),
+				WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
 				WithPASKSReady, markOld, WithPAStatusService(testRevision),
 				WithPAMetricsService(privateSvc), WithObservedGeneration(1)),
 			sks(testNamespace, testRevision, WithDeployRef(deployName), WithProxyMode, WithSKSReady),
@@ -693,8 +693,8 @@ func TestReconcile(t *testing.T) {
 		Ctx: context.WithValue(context.Background(), deciderKey{},
 			decider(testNamespace, testRevision, 0 /* desiredScale */, 0 /* ebc */, scaling.MinActivators)),
 		Objects: []runtime.Object{
-			kpa(testNamespace, testRevision, withScales(0, 0),
-				WithNoTraffic("NoTraffic", "The target is not receiving traffic."),
+			kpa(testNamespace, testRevision, WithScaleTargetInitialized, withScales(0, 0),
+				WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
 				WithPASKSReady, markOld, WithPAStatusService(testRevision),
 				WithPAMetricsService(privateSvc), WithObservedGeneration(1)),
 			sks(testNamespace, testRevision, WithDeployRef(deployName), WithProxyMode, WithSKSReady),
@@ -722,7 +722,7 @@ func TestReconcile(t *testing.T) {
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: kpa(testNamespace, testRevision, markScaleTargetInitialized, withScales(1, 0),
 				WithPASKSReady, WithPAMetricsService(privateSvc),
-				WithNoTraffic("NoTraffic", "The target is not receiving traffic."),
+				WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
 				WithPAStatusService(testRevision), WithPAMetricsService(privateSvc),
 				WithObservedGeneration(1)),
 		}},
@@ -796,7 +796,7 @@ func TestReconcile(t *testing.T) {
 			defaultMetric,
 		}, underscaledReady...),
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
-			Object: activatingKPAMinScale(underscale),
+			Object: activatingKPAMinScale(underscale, WithScaleTargetInitialized),
 		}},
 		WantPatches: []clientgotesting.PatchActionImpl{
 			minScalePatch,
@@ -909,8 +909,8 @@ func TestReconcile(t *testing.T) {
 			decider(testNamespace, testRevision, unknownScale, /* desiredScale */
 				0 /* ebc */, scaling.MinActivators)),
 		Objects: []runtime.Object{
-			kpa(testNamespace, testRevision, WithPASKSReady,
-				WithNoTraffic("NoTraffic", "The target is not receiving traffic."), WithPAMetricsService(privateSvc),
+			kpa(testNamespace, testRevision, WithScaleTargetInitialized, WithPASKSReady,
+				WithNoTraffic(noTrafficReason, "The target is not receiving traffic."), WithPAMetricsService(privateSvc),
 				withScales(0, -1), WithPAStatusService(testRevision), WithObservedGeneration(1)),
 			sks(testNamespace, testRevision, WithDeployRef(deployName),
 				WithProxyMode, WithSKSReady),
@@ -1056,7 +1056,7 @@ func TestReconcile(t *testing.T) {
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: kpa(testNamespace, testRevision, markScaleTargetInitialized,
-				WithNoTraffic("NoTraffic", "The target is not receiving traffic."),
+				WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
 				withScales(0, -1), WithReachabilityReachable,
 				WithPAMetricsService(privateSvc), WithObservedGeneration(1),
 				WithPASKSNotReady(""),
@@ -1107,6 +1107,30 @@ func TestReconcile(t *testing.T) {
 				WithPAMetricsService(privateSvc), WithObservedGeneration(1),
 			),
 		}},
+	}, {
+		Name: "mark initial scale reached for an existing inactive PA",
+		Key:  key,
+		Ctx: context.WithValue(context.Background(), deciderKey{},
+			decider(testNamespace, testRevision, -1, /* desiredScale */
+				-42 /* ebc */, scaling.MinActivators)),
+		Objects: append([]runtime.Object{
+			kpa(testNamespace, testRevision, WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
+				withScales(0, -1), WithReachabilityReachable, WithPAStatusService(testRevision), WithPAMetricsService(privateSvc),
+				WithPASKSReady,
+			),
+			sks(testNamespace, testRevision, WithDeployRef(deployName), WithProxyMode, WithSKSReady),
+			metric(testNamespace, testRevision),
+			deploy(testNamespace, testRevision, func(d *appsv1.Deployment) {
+				d.Spec.Replicas = ptr.Int32(2)
+			}),
+		}),
+		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
+			Object: kpa(testNamespace, testRevision, WithNoTraffic(noTrafficReason, "The target is not receiving traffic."),
+				WithPASKSReady, markScaleTargetInitialized,
+				withScales(0, -1), WithReachabilityReachable, WithPAStatusService(testRevision),
+				WithPAMetricsService(privateSvc), WithObservedGeneration(1),
+			),
+		}},
 	}}
 
 	table.Test(t, MakeFactory(func(ctx context.Context, listers *Listers, cmw configmap.Watcher) controller.Reconciler {
diff --git a/pkg/reconciler/route/resources/ingress_test.go b/pkg/reconciler/route/resources/ingress_test.go
index d754490ae..998dc7c4a 100644
--- a/pkg/reconciler/route/resources/ingress_test.go
+++ b/pkg/reconciler/route/resources/ingress_test.go
@@ -130,6 +130,8 @@ func TestMakeIngressSpec_CorrectRules(t *testing.T) {
 
 	expected := []netv1alpha1.IngressRule{{
 		Hosts: []string{
+			"test-route." + ns,
+			"test-route." + ns + ".svc",
 			"test-route." + ns + ".svc.cluster.local",
 		},
 		HTTP: &netv1alpha1.HTTPIngressRuleValue{
@@ -174,6 +176,8 @@ func TestMakeIngressSpec_CorrectRules(t *testing.T) {
 		Visibility: netv1alpha1.IngressVisibilityExternalIP,
 	}, {
 		Hosts: []string{
+			"v1-test-route." + ns,
+			"v1-test-route." + ns + ".svc",
 			"v1-test-route." + ns + ".svc.cluster.local",
 		},
 		HTTP: &netv1alpha1.HTTPIngressRuleValue{
@@ -234,7 +238,7 @@ func TestMakeIngressSpec_CorrectRuleVisibility(t *testing.T) {
 		route              *v1.Route
 		targets            map[string]traffic.RevisionTargets
 		serviceVisibility  map[string]netv1alpha1.IngressVisibility
-		expectedVisibility map[string]netv1alpha1.IngressVisibility
+		expectedVisibility map[netv1alpha1.IngressVisibility][]string
 	}{{
 		name:  "public route",
 		route: Route("default", "myroute", WithURL),
@@ -249,9 +253,9 @@ func TestMakeIngressSpec_CorrectRuleVisibility(t *testing.T) {
 				Active:      true,
 			}},
 		},
-		expectedVisibility: map[string]netv1alpha1.IngressVisibility{
-			"myroute.default.svc.cluster.local": netv1alpha1.IngressVisibilityClusterLocal,
-			"myroute.default.example.com":       netv1alpha1.IngressVisibilityExternalIP,
+		expectedVisibility: map[netv1alpha1.IngressVisibility][]string{
+			netv1alpha1.IngressVisibilityClusterLocal: {"myroute.default", "myroute.default.svc", "myroute.default.svc.cluster.local"},
+			netv1alpha1.IngressVisibilityExternalIP:   {"myroute.default.example.com"},
 		},
 	}, {
 		name:  "private route",
@@ -270,8 +274,8 @@ func TestMakeIngressSpec_CorrectRuleVisibility(t *testing.T) {
 		serviceVisibility: map[string]netv1alpha1.IngressVisibility{
 			traffic.DefaultTarget: netv1alpha1.IngressVisibilityClusterLocal,
 		},
-		expectedVisibility: map[string]netv1alpha1.IngressVisibility{
-			"myroute.default.svc.cluster.local": netv1alpha1.IngressVisibilityClusterLocal,
+		expectedVisibility: map[netv1alpha1.IngressVisibility][]string{
+			netv1alpha1.IngressVisibilityClusterLocal: {"myroute.default", "myroute.default.svc", "myroute.default.svc.cluster.local"},
 		},
 	}, {
 		name:  "unspecified route",
@@ -287,9 +291,9 @@ func TestMakeIngressSpec_CorrectRuleVisibility(t *testing.T) {
 				Active:      true,
 			}},
 		},
-		expectedVisibility: map[string]netv1alpha1.IngressVisibility{
-			"myroute.default.svc.cluster.local": netv1alpha1.IngressVisibilityClusterLocal,
-			"myroute.default.example.com":       netv1alpha1.IngressVisibilityExternalIP,
+		expectedVisibility: map[netv1alpha1.IngressVisibility][]string{
+			netv1alpha1.IngressVisibilityClusterLocal: {"myroute.default", "myroute.default.svc", "myroute.default.svc.cluster.local"},
+			netv1alpha1.IngressVisibilityExternalIP:   {"myroute.default.example.com"},
 		},
 	}}
 	for _, c := range cases {
@@ -302,10 +306,9 @@ func TestMakeIngressSpec_CorrectRuleVisibility(t *testing.T) {
 				t.Errorf("Unexpected %d rules, saw %d", len(c.expectedVisibility), len(ci.Rules))
 			}
 			for _, rule := range ci.Rules {
-				domain := rule.Hosts[0]
 				visibility := rule.Visibility
-				if c.expectedVisibility[domain] != visibility {
-					t.Errorf("Expected visibility %s for host %s, saw %s", c.expectedVisibility, domain, visibility)
+				if !cmp.Equal(c.expectedVisibility[visibility], rule.Hosts) {
+					t.Errorf("Expected hosts %s for visibility %s, saw %s", c.expectedVisibility, visibility, rule.Hosts)
 				}
 			}
 		})
@@ -338,6 +341,8 @@ func TestMakeIngressSpec_CorrectRulesWithTagBasedRouting(t *testing.T) {
 
 	expected := []netv1alpha1.IngressRule{{
 		Hosts: []string{
+			"test-route." + ns,
+			"test-route." + ns + ".svc",
 			"test-route." + ns + ".svc.cluster.local",
 		},
 		HTTP: &netv1alpha1.HTTPIngressRuleValue{
@@ -426,6 +431,8 @@ func TestMakeIngressSpec_CorrectRulesWithTagBasedRouting(t *testing.T) {
 		Visibility: netv1alpha1.IngressVisibilityExternalIP,
 	}, {
 		Hosts: []string{
+			"v1-test-route." + ns,
+			"v1-test-route." + ns + ".svc",
 			"v1-test-route." + ns + ".svc.cluster.local",
 		},
 		HTTP: &netv1alpha1.HTTPIngressRuleValue{
@@ -980,6 +987,8 @@ func TestMakeIngressACMEChallenges(t *testing.T) {
 
 	expected := []netv1alpha1.IngressRule{{
 		Hosts: []string{
+			"test-route.test-ns",
+			"test-route.test-ns.svc",
 			"test-route.test-ns.svc.cluster.local",
 		},
 		Visibility: netv1alpha1.IngressVisibilityClusterLocal,
diff --git a/pkg/reconciler/route/route_test.go b/pkg/reconciler/route/route_test.go
index 01bc935b8..c2698ab0f 100644
--- a/pkg/reconciler/route/route_test.go
+++ b/pkg/reconciler/route/route_test.go
@@ -208,6 +208,8 @@ func TestCreateRouteForOneReserveRevision(t *testing.T) {
 		TLS: []v1alpha1.IngressTLS{},
 		Rules: []v1alpha1.IngressRule{{
 			Hosts: []string{
+				"test-route.test",
+				"test-route.test.svc",
 				"test-route.test.svc.cluster.local",
 			},
 			Visibility: v1alpha1.IngressVisibilityClusterLocal,
@@ -337,6 +339,8 @@ func TestCreateRouteWithMultipleTargets(t *testing.T) {
 		TLS: []v1alpha1.IngressTLS{},
 		Rules: []v1alpha1.IngressRule{{
 			Hosts: []string{
+				"test-route.test",
+				"test-route.test.svc",
 				"test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -454,6 +458,8 @@ func TestCreateRouteWithOneTargetReserve(t *testing.T) {
 		TLS: []v1alpha1.IngressTLS{},
 		Rules: []v1alpha1.IngressRule{{
 			Hosts: []string{
+				"test-route.test",
+				"test-route.test.svc",
 				"test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -585,6 +591,8 @@ func TestCreateRouteWithDuplicateTargets(t *testing.T) {
 		TLS: []v1alpha1.IngressTLS{},
 		Rules: []v1alpha1.IngressRule{{
 			Hosts: []string{
+				"test-route.test",
+				"test-route.test.svc",
 				"test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -651,6 +659,8 @@ func TestCreateRouteWithDuplicateTargets(t *testing.T) {
 			Visibility: v1alpha1.IngressVisibilityExternalIP,
 		}, {
 			Hosts: []string{
+				"test-revision-1-test-route.test",
+				"test-revision-1-test-route.test.svc",
 				"test-revision-1-test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -695,6 +705,8 @@ func TestCreateRouteWithDuplicateTargets(t *testing.T) {
 			Visibility: v1alpha1.IngressVisibilityExternalIP,
 		}, {
 			Hosts: []string{
+				"test-revision-2-test-route.test",
+				"test-revision-2-test-route.test.svc",
 				"test-revision-2-test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -791,6 +803,8 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 		TLS: []v1alpha1.IngressTLS{},
 		Rules: []v1alpha1.IngressRule{{
 			Hosts: []string{
+				"test-route.test",
+				"test-route.test.svc",
 				"test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -857,6 +871,8 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 			Visibility: v1alpha1.IngressVisibilityExternalIP,
 		}, {
 			Hosts: []string{
+				"bar-test-route.test",
+				"bar-test-route.test.svc",
 				"bar-test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -901,6 +917,8 @@ func TestCreateRouteWithNamedTargets(t *testing.T) {
 			Visibility: v1alpha1.IngressVisibilityExternalIP,
 		}, {
 			Hosts: []string{
+				"foo-test-route.test",
+				"foo-test-route.test.svc",
 				"foo-test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -1006,6 +1024,8 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 		TLS: []v1alpha1.IngressTLS{},
 		Rules: []v1alpha1.IngressRule{{
 			Hosts: []string{
+				"test-route.test",
+				"test-route.test.svc",
 				"test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -1162,6 +1182,8 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 			Visibility: v1alpha1.IngressVisibilityExternalIP,
 		}, {
 			Hosts: []string{
+				"bar-test-route.test",
+				"bar-test-route.test.svc",
 				"bar-test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
@@ -1212,6 +1234,8 @@ func TestCreateRouteWithNamedTargetsAndTagBasedRouting(t *testing.T) {
 			Visibility: v1alpha1.IngressVisibilityExternalIP,
 		}, {
 			Hosts: []string{
+				"foo-test-route.test",
+				"foo-test-route.test.svc",
 				"foo-test-route.test.svc.cluster.local",
 			},
 			HTTP: &v1alpha1.HTTPIngressRuleValue{
diff --git a/pkg/reconciler/route/table_test.go b/pkg/reconciler/route/table_test.go
index a218de31a..ad30331c5 100644
--- a/pkg/reconciler/route/table_test.go
+++ b/pkg/reconciler/route/table_test.go
@@ -77,12 +77,13 @@ func TestReconcile(t *testing.T) {
 	}, {
 		Name: "configuration not yet ready",
 		Objects: []runtime.Object{
-			Route("default", "first-reconcile", WithConfigTarget("not-ready"), WithRouteGeneration(1)),
+			Route("default", "first-reconcile", WithConfigTarget("not-ready"), WithRouteGeneration(2009)),
 			cfg("default", "not-ready", WithConfigGeneration(1), WithLatestCreated("not-ready-00001")),
 			rev("default", "not-ready", 1, WithInitRevConditions, WithRevName("not-ready-00001")),
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "first-reconcile", WithConfigTarget("not-ready"), WithURL,
+				WithRouteGeneration(2009), WithRouteObservedGeneration,
 				// The first reconciliation initializes the conditions and reflects
 				// that the referenced configuration is not yet ready.
 				WithInitRouteConditions, MarkConfigurationNotReady("not-ready")),
@@ -91,7 +92,8 @@ func TestReconcile(t *testing.T) {
 	}, {
 		Name: "configuration permanently failed",
 		Objects: []runtime.Object{
-			Route("default", "first-reconcile", WithConfigTarget("permanently-failed"), WithRouteGeneration(1)),
+			Route("default", "first-reconcile", WithConfigTarget("permanently-failed"),
+				WithRouteGeneration(2020)),
 			cfg("default", "permanently-failed",
 				WithConfigGeneration(1), WithLatestCreated("permanently-failed-00001"), MarkLatestCreatedFailed("blah")),
 			rev("default", "permanently-failed", 1,
@@ -100,6 +102,7 @@ func TestReconcile(t *testing.T) {
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "first-reconcile", WithConfigTarget("permanently-failed"), WithURL,
+				WithRouteGeneration(2020), WithRouteObservedGeneration,
 				WithInitRouteConditions, MarkConfigurationFailed("permanently-failed")),
 		}},
 		Key: "default/first-reconcile",
@@ -110,12 +113,14 @@ func TestReconcile(t *testing.T) {
 			InduceFailure("update", "routes"),
 		},
 		Objects: []runtime.Object{
-			Route("default", "first-reconcile", WithConfigTarget("not-ready"), WithRouteGeneration(1)),
+			Route("default", "first-reconcile", WithConfigTarget("not-ready"),
+				WithRouteGeneration(42)),
 			cfg("default", "not-ready", WithConfigGeneration(1), WithLatestCreated("not-ready-00001")),
 			rev("default", "not-ready", 1, WithInitRevConditions, WithRevName("not-ready-00001")),
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "first-reconcile", WithConfigTarget("not-ready"), WithURL,
+				WithRouteGeneration(42), WithRouteObservedGeneration,
 				WithInitRouteConditions, MarkConfigurationNotReady("not-ready")),
 		}},
 		WantEvents: []string{
@@ -126,15 +131,15 @@ func TestReconcile(t *testing.T) {
 	}, {
 		Name: "simple route becomes ready, ingress unknown",
 		Objects: []runtime.Object{
-			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34"), WithRouteGeneration(1)),
+			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34"),
+				WithRouteGeneration(1955)),
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithServiceName("mcd")),
 		},
 		WantCreates: []runtime.Object{
 			simpleIngress(
-				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL,
-					WithRouteUID("12-34"), WithRouteGeneration(1)),
+				Route("default", "becomes-ready", WithConfigTarget("config"), WithURL, WithRouteUID("12-34")),
 				&traffic.Config{
 					Targets: map[string]traffic.RevisionTargets{
 						traffic.DefaultTarget: {{
@@ -157,7 +162,7 @@ func TestReconcile(t *testing.T) {
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "becomes-ready", WithConfigTarget("config"),
-				WithRouteUID("12-34"), WithRouteGeneration(1), WithRouteObservedGeneration,
+				WithRouteUID("12-34"), WithRouteGeneration(1955), WithRouteObservedGeneration,
 				// Populated by reconciliation when all traffic has been assigned.
 				WithURL, WithAddress, WithRouteConditionsAutoTLSDisabled,
 				MarkTrafficAssigned, MarkIngressNotConfigured, WithStatusTraffic(
@@ -333,7 +338,7 @@ func TestReconcile(t *testing.T) {
 	}, {
 		Name: "simple route becomes ready",
 		Objects: []runtime.Object{
-			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteGeneration(1)),
+			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteGeneration(2009)),
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
@@ -363,7 +368,8 @@ func TestReconcile(t *testing.T) {
 			Object: Route("default", "becomes-ready", WithConfigTarget("config"),
 				// Populated by reconciliation when the route becomes ready.
 				WithURL, WithAddress, WithRouteConditionsAutoTLSDisabled,
-				MarkTrafficAssigned, MarkIngressReady, WithRouteObservedGeneration, WithStatusTraffic(
+				WithRouteGeneration(2009), WithRouteObservedGeneration,
+				MarkTrafficAssigned, MarkIngressReady, WithStatusTraffic(
 					v1.TrafficTarget{
 						RevisionName:   "config-00001",
 						Percent:        ptr.Int64(100),
@@ -376,13 +382,14 @@ func TestReconcile(t *testing.T) {
 		Key: "default/becomes-ready",
 	}, {
 		Name: "failure creating k8s placeholder service",
-		// We induce a failure creating the placeholder service
+		// We induce a failure creating the placeholder service.
 		WantErr: true,
 		WithReactors: []clientgotesting.ReactionFunc{
 			InduceFailure("create", "services"),
 		},
 		Objects: []runtime.Object{
-			Route("default", "create-svc-failure", WithConfigTarget("config"), WithRouteFinalizer, WithRouteGeneration(1)),
+			Route("default", "create-svc-failure", WithConfigTarget("config"), WithRouteFinalizer,
+				WithRouteGeneration(2007)),
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001")),
@@ -395,6 +402,7 @@ func TestReconcile(t *testing.T) {
 				WithRouteFinalizer,
 				// Populated by reconciliation when we've failed to create
 				// the K8s service.
+				WithRouteGeneration(2007), WithRouteObservedGeneration,
 				WithURL, WithAddress, WithInitRouteConditions,
 				MarkTrafficAssigned, WithStatusTraffic(
 					v1.TrafficTarget{
@@ -1220,12 +1228,14 @@ func TestReconcile(t *testing.T) {
 	}, {
 		Name: "revision missing (direct)",
 		Objects: []runtime.Object{
-			Route("default", "missing-revision-direct", WithRevTarget("not-found"), WithRouteGeneration(1)),
+			Route("default", "missing-revision-direct", WithRevTarget("not-found"),
+				WithRouteGeneration(1988)),
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "missing-revision-direct", WithRevTarget("not-found"), WithURL,
+				WithRouteGeneration(1988), WithRouteObservedGeneration,
 				WithInitRouteConditions, MarkMissingTrafficTarget("Revision", "not-found")),
 		}},
 		PostConditions: []func(*testing.T, *TableRow){
@@ -1235,12 +1245,14 @@ func TestReconcile(t *testing.T) {
 	}, {
 		Name: "revision missing (indirect)",
 		Objects: []runtime.Object{
-			Route("default", "missing-revision-indirect", WithConfigTarget("config"), WithRouteGeneration(1)),
+			Route("default", "missing-revision-indirect", WithConfigTarget("config"),
+				WithRouteGeneration(2006)),
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "missing-revision-indirect", WithConfigTarget("config"), WithURL,
+				WithRouteGeneration(2006), WithRouteObservedGeneration,
 				WithInitRouteConditions, MarkMissingTrafficTarget("Revision", "config-00001")),
 		}},
 		Key: "default/missing-revision-indirect",
@@ -1539,7 +1551,7 @@ func TestReconcile(t *testing.T) {
 		Objects: []runtime.Object{
 			Route("default", "switch-configs", WithConfigTarget("green"),
 				WithURL, WithAddress, WithRouteConditionsAutoTLSDisabled,
-				MarkTrafficAssigned, MarkIngressReady, WithRouteGeneration(1), WithRouteObservedGeneration,
+				MarkTrafficAssigned, MarkIngressReady, WithRouteGeneration(1984), WithRouteObservedGeneration,
 				WithStatusTraffic(
 					v1.TrafficTarget{
 						Tag:          "blue",
@@ -1595,7 +1607,8 @@ func TestReconcile(t *testing.T) {
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "switch-configs", WithConfigTarget("green"),
 				WithURL, WithAddress, WithRouteConditionsAutoTLSDisabled,
-				MarkTrafficAssigned, MarkIngressReady, WithRouteObservedGeneration, WithStatusTraffic(
+				WithRouteGeneration(1984), MarkTrafficAssigned, MarkIngressReady,
+				WithRouteObservedGeneration, WithStatusTraffic(
 					v1.TrafficTarget{
 						RevisionName:   "green-00001",
 						Percent:        ptr.Int64(100),
@@ -1917,12 +1930,13 @@ func TestReconcile_ResponsiveGC(t *testing.T) {
 	}))
 }
 
-func TestReconcile_EnableAutoTLS(t *testing.T) {
+func TestReconcileEnableAutoTLS(t *testing.T) {
 	table := TableTest{{
 		Name: "check that existing wildcard cert is used when creating a Route",
 		Objects: []runtime.Object{
 			wildcardCert("default", "example.com"),
-			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteUID("12-34")),
+			Route("default", "becomes-ready", WithConfigTarget("config"), WithRouteGeneration(1982),
+				WithRouteUID("12-34")),
 			cfg("default", "config",
 				WithConfigGeneration(1), WithLatestCreated("config-00001"), WithLatestReady("config-00001")),
 			rev("default", "config", 1, MarkRevisionReady, WithRevName("config-00001"), WithServiceName("mcd")),
@@ -1958,7 +1972,7 @@ func TestReconcile_EnableAutoTLS(t *testing.T) {
 		},
 		WantStatusUpdates: []clientgotesting.UpdateActionImpl{{
 			Object: Route("default", "becomes-ready", WithConfigTarget("config"),
-				WithRouteUID("12-34"), WithRouteGeneration(1), WithRouteObservedGeneration,
+				WithRouteUID("12-34"), WithRouteGeneration(1982), WithRouteObservedGeneration,
 				// Populated by reconciliation when all traffic has been assigned.
 				WithAddress, WithInitRouteConditions,
 				MarkTrafficAssigned, MarkIngressNotConfigured, WithStatusTraffic(
diff --git a/pkg/testing/v1/route.go b/pkg/testing/v1/route.go
index 26ecaf4e8..1fb45795d 100644
--- a/pkg/testing/v1/route.go
+++ b/pkg/testing/v1/route.go
@@ -44,14 +44,14 @@ func WithSpecTraffic(traffic ...v1.TrafficTarget) RouteOption {
 // WithRouteUID sets the Route's UID
 func WithRouteUID(uid types.UID) RouteOption {
 	return func(r *v1.Route) {
-		r.ObjectMeta.UID = uid
+		r.UID = uid
 	}
 }
 
 // WithRouteGeneration sets the route's generation
 func WithRouteGeneration(generation int64) RouteOption {
 	return func(r *v1.Route) {
-		r.Status.ObservedGeneration = generation
+		r.Generation = generation
 	}
 }
 
diff --git a/test/e2e-basic-entrypoint.sh b/test/e2e-basic-entrypoint.sh
deleted file mode 100644
index 96b00ab4b..000000000
--- a/test/e2e-basic-entrypoint.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env bash
-
-# 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.
-
-# This script is a workaround supporing running e2e-tests.sh and
-# e2e-auto-tls-test.sh for Prow jobs that run both of them as supported before.
-# This is introduced as test-infra doesn't support running multiple selected
-# test scripts yet. See https://github.com/knative/test-infra/issues/1746
-
-cur_dir="$(dirname ${BASH_SOURCE})"
-
-"${cur_dir}/e2e-tests.sh" $@
-"${cur_dir}/e2e-auto-tls-tests.sh" $@
diff --git a/test/e2e-common.sh b/test/e2e-common.sh
index ed4777682..1426b02ff 100644
--- a/test/e2e-common.sh
+++ b/test/e2e-common.sh
@@ -24,6 +24,7 @@ E2E_CLUSTER_MACHINE=${E2E_CLUSTER_MACHINE:-e2-standard-8}
 
 # This script provides helper methods to perform cluster actions.
 source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/e2e-tests.sh
+source $(dirname $0)/e2e-networking-library.sh
 
 CERT_MANAGER_VERSION="0.12.0"
 # Since default is istio, make default ingress as istio
@@ -185,123 +186,6 @@ function install_knative_serving() {
   done
 }
 
-function install_istio() {
-  if [[ -z "${ISTIO_VERSION}" ]]; then
-    readonly ISTIO_VERSION="stable"
-  fi
-
-  local NET_ISTIO_DIR=$(mktemp -d)
-  git clone --quiet --branch master https://github.com/knative-sandbox/net-istio.git ${NET_ISTIO_DIR}
-  git --git-dir "${NET_ISTIO_DIR}/.git" checkout 7398a24a5fa9b06154ce5ef6b551fce856591b08
-
-  if (( MESH )); then
-    ISTIO_PROFILE="istio-ci-mesh.yaml"
-  else
-    ISTIO_PROFILE="istio-ci-no-mesh.yaml"
-  fi
-
-  echo ">> Installing Istio"
-  echo "Istio version: ${ISTIO_VERSION}"
-  echo "Istio profile: ${ISTIO_PROFILE}"
-  ${NET_ISTIO_DIR}/third_party/istio-${ISTIO_VERSION}/install-istio.sh ${ISTIO_PROFILE}
-
-  if [[ -n "$1" ]]; then
-    echo ">> Installing net-istio"
-    echo "net-istio original YAML: ${1}"
-    # Create temp copy in which we replace knative-serving by the test's system namespace.
-    local YAML_NAME=$(mktemp -p $TMP_DIR --suffix=.$(basename "$1"))
-    sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${1} > ${YAML_NAME}
-    echo "net-istio patched YAML: $YAML_NAME"
-    ko apply -f "${YAML_NAME}" --selector=networking.knative.dev/ingress-provider=istio || return 1
-    UNINSTALL_LIST+=( "${YAML_NAME}" )
-  fi
-}
-
-function install_gloo() {
-  local INSTALL_GLOO_YAML="./third_party/gloo-latest/gloo.yaml"
-  echo "Gloo YAML: ${INSTALL_GLOO_YAML}"
-  echo ">> Bringing up Gloo"
-
-  kubectl apply -f ${INSTALL_GLOO_YAML} || return 1
-  UNINSTALL_LIST+=( "${INSTALL_GLOO_YAML}" )
-
-  echo ">> Patching Gloo"
-  # Scale replicas of the Gloo proxies to handle large qps
-  kubectl scale -n gloo-system deployment knative-external-proxy --replicas=6
-  kubectl scale -n gloo-system deployment knative-internal-proxy --replicas=6
-}
-
-function install_kourier() {
-  local INSTALL_KOURIER_YAML="./third_party/kourier-latest/kourier.yaml"
-  echo "Kourier YAML: ${INSTALL_KOURIER_YAML}"
-  echo ">> Bringing up Kourier"
-
-  kubectl apply -f ${INSTALL_KOURIER_YAML} || return 1
-  UNINSTALL_LIST+=( "${INSTALL_KOURIER_YAML}" )
-
-  echo ">> Patching Kourier"
-  # Scale replicas of the Kourier gateways to handle large qps
-  kubectl scale -n kourier-system deployment 3scale-kourier-gateway --replicas=6
-}
-
-function install_kong() {
-  local INSTALL_KONG_YAML="./third_party/kong-latest/kong.yaml"
-  echo "Kong YAML: ${INSTALL_KONG_YAML}"
-  echo ">> Bringing up Kong"
-
-  kubectl apply -f ${INSTALL_KONG_YAML} || return 1
-  UNINSTALL_LIST+=( "${INSTALL_KONG_YAML}" )
-
-  echo ">> Patching Kong"
-  # Scale replicas of the Kong gateways to handle large qps
-  kubectl scale -n kong deployment ingress-kong --replicas=6
-}
-
-function install_ambassador() {
-  local AMBASSADOR_MANIFESTS_PATH="./third_party/ambassador-latest/"
-  echo "Ambassador YAML: ${AMBASSADOR_MANIFESTS_PATH}"
-
-  echo ">> Creating namespace 'ambassador'"
-  kubectl create namespace ambassador || return 1
-
-  echo ">> Installing Ambassador"
-  kubectl apply -n ambassador -f ${AMBASSADOR_MANIFESTS_PATH} || return 1
-  UNINSTALL_LIST+=( "${AMBASSADOR_MANIFESTS_PATH}" )
-
-#  echo ">> Fixing Ambassador's permissions"
-#  kubectl patch clusterrolebinding ambassador -p '{"subjects":[{"kind": "ServiceAccount", "name": "ambassador", "namespace": "ambassador"}]}' || return 1
-
-#  echo ">> Enabling Knative support in Ambassador"
-#  kubectl set env --namespace ambassador deployments/ambassador AMBASSADOR_KNATIVE_SUPPORT=true || return 1
-
-  echo ">> Patching Ambassador"
-  # Scale replicas of the Ambassador gateway to handle large qps
-  kubectl scale -n ambassador deployment ambassador --replicas=6
-}
-
-function install_contour() {
-  local INSTALL_CONTOUR_YAML="./third_party/contour-latest/contour.yaml"
-  local INSTALL_NET_CONTOUR_YAML="./third_party/contour-latest/net-contour.yaml"
-  echo "Contour YAML: ${INSTALL_CONTOUR_YAML}"
-  echo "Contour KIngress YAML: ${INSTALL_NET_CONTOUR_YAML}"
-
-  echo ">> Bringing up Contour"
-  sed 's/--log-level info/--log-level debug/g' "${INSTALL_CONTOUR_YAML}" | kubectl apply -f - || return 1
-
-  UNINSTALL_LIST+=( "${INSTALL_CONTOUR_YAML}" )
-  HA_COMPONENTS+=( "contour-ingress-controller" )
-
-  local NET_CONTOUR_YAML_NAME=${TMP_DIR}/${INSTALL_NET_CONTOUR_YAML##*/}
-  sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${INSTALL_NET_CONTOUR_YAML} > ${NET_CONTOUR_YAML_NAME}
-  echo ">> Bringing up net-contour"
-  kubectl apply -f ${NET_CONTOUR_YAML_NAME} || return 1
-
-  # Disable verbosity until https://github.com/golang/go/issues/40771 is fixed.
-  export GO_TEST_VERBOSITY=standard-quiet
-
-  UNINSTALL_LIST+=( "${NET_CONTOUR_YAML_NAME}" )
-}
-
 # Installs Knative Serving in the current cluster, and waits for it to be ready.
 # If no parameters are passed, installs the current source-based build.
 # Parameters: $1 - Knative Serving version "HEAD" or "latest-release".
@@ -502,22 +386,6 @@ function knative_teardown() {
   fi
 }
 
-
-
-# Add function call to trap
-# Parameters: $1 - Function to call
-#             $2...$n - Signals for trap
-function add_trap() {
-  local cmd=$1
-  shift
-  for trap_signal in $@; do
-    local current_trap="$(trap -p $trap_signal | cut -d\' -f2)"
-    local new_cmd="($cmd)"
-    [[ -n "${current_trap}" ]] && new_cmd="${current_trap};${new_cmd}"
-    trap -- "${new_cmd}" $trap_signal
-  done
-}
-
 # Create test resources and images
 function test_setup() {
   echo ">> Replacing ${KNATIVE_DEFAULT_NAMESPACE} with the actual namespace for Knative Serving..."
@@ -559,51 +427,7 @@ function test_setup() {
   wait_until_pods_running cert-manager || return 1
 
   echo ">> Waiting for Ingress provider to be running..."
-  if [[ -n "${ISTIO_VERSION}" ]]; then
-    wait_until_pods_running istio-system || return 1
-    wait_until_service_has_external_http_address istio-system istio-ingressgateway
-  fi
-  if [[ -n "${GLOO_VERSION}" ]]; then
-    # we must set these override values to allow the test spoofing client to work with Gloo
-    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
-    export GATEWAY_OVERRIDE=knative-external-proxy
-    export GATEWAY_NAMESPACE_OVERRIDE=gloo-system
-    wait_until_pods_running gloo-system || return 1
-    wait_until_service_has_external_ip gloo-system knative-external-proxy
-  fi
-  if [[ -n "${KOURIER_VERSION}" ]]; then
-    # we must set these override values to allow the test spoofing client to work with Kourier
-    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
-    export GATEWAY_OVERRIDE=kourier
-    export GATEWAY_NAMESPACE_OVERRIDE=kourier-system
-    wait_until_pods_running kourier-system || return 1
-    wait_until_service_has_external_http_address kourier-system kourier
-  fi
-  if [[ -n "${AMBASSADOR_VERSION}" ]]; then
-    # we must set these override values to allow the test spoofing client to work with Ambassador
-    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
-    export GATEWAY_OVERRIDE=ambassador
-    export GATEWAY_NAMESPACE_OVERRIDE=ambassador
-    wait_until_pods_running ambassador || return 1
-    wait_until_service_has_external_http_address ambassador ambassador
-  fi
-  if [[ -n "${CONTOUR_VERSION}" ]]; then
-    # we must set these override values to allow the test spoofing client to work with Contour
-    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
-    export GATEWAY_OVERRIDE=envoy
-    export GATEWAY_NAMESPACE_OVERRIDE=contour-external
-    wait_until_pods_running contour-external || return 1
-    wait_until_pods_running contour-internal || return 1
-    wait_until_service_has_external_ip "${GATEWAY_NAMESPACE_OVERRIDE}" "${GATEWAY_OVERRIDE}"
-  fi
-  if [[ -n "${KONG_VERSION}" ]]; then
-    # we must set these override values to allow the test spoofing client to work with Kong
-    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
-    export GATEWAY_OVERRIDE=kong-proxy
-    export GATEWAY_NAMESPACE_OVERRIDE=kong
-    wait_until_pods_running kong || return 1
-    wait_until_service_has_external_http_address kong kong-proxy
-  fi
+  wait_until_ingress_running || return 1
 
   if (( INSTALL_MONITORING )); then
     echo ">> Waiting for Monitoring to be running..."
diff --git a/test/e2e-networking-library.sh b/test/e2e-networking-library.sh
new file mode 100644
index 000000000..d0f2da559
--- /dev/null
+++ b/test/e2e-networking-library.sh
@@ -0,0 +1,181 @@
+#!/usr/bin/env bash
+
+# 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.
+
+function install_istio() {
+  if [[ -z "${ISTIO_VERSION}" ]]; then
+    readonly ISTIO_VERSION="stable"
+  fi
+
+  local NET_ISTIO_DIR=$(mktemp -d)
+  git clone --quiet --branch master https://github.com/knative-sandbox/net-istio.git ${NET_ISTIO_DIR}
+  git --git-dir "${NET_ISTIO_DIR}/.git" checkout 7398a24a5fa9b06154ce5ef6b551fce856591b08
+
+  if (( MESH )); then
+    ISTIO_PROFILE="istio-ci-mesh.yaml"
+  else
+    ISTIO_PROFILE="istio-ci-no-mesh.yaml"
+  fi
+
+  echo ">> Installing Istio"
+  echo "Istio version: ${ISTIO_VERSION}"
+  echo "Istio profile: ${ISTIO_PROFILE}"
+  ${NET_ISTIO_DIR}/third_party/istio-${ISTIO_VERSION}/install-istio.sh ${ISTIO_PROFILE}
+
+  if [[ -n "$1" ]]; then
+    echo ">> Installing net-istio"
+    echo "net-istio original YAML: ${1}"
+    # Create temp copy in which we replace knative-serving by the test's system namespace.
+    local YAML_NAME=$(mktemp -p $TMP_DIR --suffix=.$(basename "$1"))
+    sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${1} > ${YAML_NAME}
+    echo "net-istio patched YAML: $YAML_NAME"
+    ko apply -f "${YAML_NAME}" --selector=networking.knative.dev/ingress-provider=istio || return 1
+    UNINSTALL_LIST+=( "${YAML_NAME}" )
+  fi
+}
+
+function install_gloo() {
+  local INSTALL_GLOO_YAML="./third_party/gloo-latest/gloo.yaml"
+  echo "Gloo YAML: ${INSTALL_GLOO_YAML}"
+  echo ">> Bringing up Gloo"
+
+  kubectl apply -f ${INSTALL_GLOO_YAML} || return 1
+  UNINSTALL_LIST+=( "${INSTALL_GLOO_YAML}" )
+
+  echo ">> Patching Gloo"
+  # Scale replicas of the Gloo proxies to handle large qps
+  kubectl scale -n gloo-system deployment knative-external-proxy --replicas=6
+  kubectl scale -n gloo-system deployment knative-internal-proxy --replicas=6
+}
+
+function install_kourier() {
+  local INSTALL_KOURIER_YAML="./third_party/kourier-latest/kourier.yaml"
+  sed -i "s/${KNATIVE_DEFAULT_NAMESPACE}/${SYSTEM_NAMESPACE}/g" ${INSTALL_KOURIER_YAML}
+  echo "Kourier YAML: ${INSTALL_KOURIER_YAML}"
+  echo ">> Bringing up Kourier"
+
+  kubectl apply -f ${INSTALL_KOURIER_YAML} || return 1
+  UNINSTALL_LIST+=( "${INSTALL_KOURIER_YAML}" )
+
+  echo ">> Patching Kourier"
+  # Scale replicas of the Kourier gateways to handle large qps
+  kubectl scale -n kourier-system deployment 3scale-kourier-gateway --replicas=6
+}
+
+function install_kong() {
+  local INSTALL_KONG_YAML="./third_party/kong-latest/kong.yaml"
+  echo "Kong YAML: ${INSTALL_KONG_YAML}"
+  echo ">> Bringing up Kong"
+
+  kubectl apply -f ${INSTALL_KONG_YAML} || return 1
+  UNINSTALL_LIST+=( "${INSTALL_KONG_YAML}" )
+
+  echo ">> Patching Kong"
+  # Scale replicas of the Kong gateways to handle large qps
+  kubectl scale -n kong deployment ingress-kong --replicas=6
+}
+
+function install_ambassador() {
+  local AMBASSADOR_MANIFESTS_PATH="./third_party/ambassador-latest/"
+  echo "Ambassador YAML: ${AMBASSADOR_MANIFESTS_PATH}"
+
+  echo ">> Creating namespace 'ambassador'"
+  kubectl create namespace ambassador || return 1
+
+  echo ">> Installing Ambassador"
+  kubectl apply -n ambassador -f ${AMBASSADOR_MANIFESTS_PATH} || return 1
+  UNINSTALL_LIST+=( "${AMBASSADOR_MANIFESTS_PATH}" )
+
+#  echo ">> Fixing Ambassador's permissions"
+#  kubectl patch clusterrolebinding ambassador -p '{"subjects":[{"kind": "ServiceAccount", "name": "ambassador", "namespace": "ambassador"}]}' || return 1
+
+#  echo ">> Enabling Knative support in Ambassador"
+#  kubectl set env --namespace ambassador deployments/ambassador AMBASSADOR_KNATIVE_SUPPORT=true || return 1
+
+  echo ">> Patching Ambassador"
+  # Scale replicas of the Ambassador gateway to handle large qps
+  kubectl scale -n ambassador deployment ambassador --replicas=6
+}
+
+function install_contour() {
+  local INSTALL_CONTOUR_YAML="./third_party/contour-latest/contour.yaml"
+  local INSTALL_NET_CONTOUR_YAML="./third_party/contour-latest/net-contour.yaml"
+  echo "Contour YAML: ${INSTALL_CONTOUR_YAML}"
+  echo "Contour KIngress YAML: ${INSTALL_NET_CONTOUR_YAML}"
+
+  echo ">> Bringing up Contour"
+  sed 's/--log-level info/--log-level debug/g' "${INSTALL_CONTOUR_YAML}" | kubectl apply -f - || return 1
+
+  UNINSTALL_LIST+=( "${INSTALL_CONTOUR_YAML}" )
+  HA_COMPONENTS+=( "contour-ingress-controller" )
+
+  local NET_CONTOUR_YAML_NAME=${TMP_DIR}/${INSTALL_NET_CONTOUR_YAML##*/}
+  sed "s/namespace: ${KNATIVE_DEFAULT_NAMESPACE}/namespace: ${SYSTEM_NAMESPACE}/g" ${INSTALL_NET_CONTOUR_YAML} > ${NET_CONTOUR_YAML_NAME}
+  echo ">> Bringing up net-contour"
+  kubectl apply -f ${NET_CONTOUR_YAML_NAME} || return 1
+
+  # Disable verbosity until https://github.com/golang/go/issues/40771 is fixed.
+  export GO_TEST_VERBOSITY=standard-quiet
+
+  UNINSTALL_LIST+=( "${NET_CONTOUR_YAML_NAME}" )
+}
+
+function wait_until_ingress_running() {
+  if [[ -n "${ISTIO_VERSION}" ]]; then
+    wait_until_pods_running istio-system || return 1
+    wait_until_service_has_external_http_address istio-system istio-ingressgateway
+  fi
+  if [[ -n "${GLOO_VERSION}" ]]; then
+    # we must set these override values to allow the test spoofing client to work with Gloo
+    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
+    export GATEWAY_OVERRIDE=knative-external-proxy
+    export GATEWAY_NAMESPACE_OVERRIDE=gloo-system
+    wait_until_pods_running gloo-system || return 1
+    wait_until_service_has_external_ip gloo-system knative-external-proxy
+  fi
+  if [[ -n "${KOURIER_VERSION}" ]]; then
+    # we must set these override values to allow the test spoofing client to work with Kourier
+    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
+    export GATEWAY_OVERRIDE=kourier
+    export GATEWAY_NAMESPACE_OVERRIDE=kourier-system
+    wait_until_pods_running kourier-system || return 1
+    wait_until_service_has_external_http_address kourier-system kourier
+  fi
+  if [[ -n "${AMBASSADOR_VERSION}" ]]; then
+    # we must set these override values to allow the test spoofing client to work with Ambassador
+    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
+    export GATEWAY_OVERRIDE=ambassador
+    export GATEWAY_NAMESPACE_OVERRIDE=ambassador
+    wait_until_pods_running ambassador || return 1
+    wait_until_service_has_external_http_address ambassador ambassador
+  fi
+  if [[ -n "${CONTOUR_VERSION}" ]]; then
+    # we must set these override values to allow the test spoofing client to work with Contour
+    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
+    export GATEWAY_OVERRIDE=envoy
+    export GATEWAY_NAMESPACE_OVERRIDE=contour-external
+    wait_until_pods_running contour-external || return 1
+    wait_until_pods_running contour-internal || return 1
+    wait_until_service_has_external_ip "${GATEWAY_NAMESPACE_OVERRIDE}" "${GATEWAY_OVERRIDE}"
+  fi
+  if [[ -n "${KONG_VERSION}" ]]; then
+    # we must set these override values to allow the test spoofing client to work with Kong
+    # see https://github.com/knative/pkg/blob/release-0.7/test/ingress/ingress.go#L37
+    export GATEWAY_OVERRIDE=kong-proxy
+    export GATEWAY_NAMESPACE_OVERRIDE=kong
+    wait_until_pods_running kong || return 1
+    wait_until_service_has_external_http_address kong kong-proxy
+  fi
+}
diff --git a/test/performance/performance-tests.sh b/test/performance/performance-tests.sh
index a577c03e2..738888c93 100755
--- a/test/performance/performance-tests.sh
+++ b/test/performance/performance-tests.sh
@@ -22,21 +22,26 @@
 export BENCHMARK_ROOT_PATH="$GOPATH/src/knative.dev/serving/test/performance/benchmarks"
 
 source vendor/knative.dev/test-infra/scripts/performance-tests.sh
+source $(dirname $0)/../e2e-networking-library.sh
+
+# Env vars required for installing Istio.
+# Install Istio no-mesh.
+export MESH=0
+export KNATIVE_DEFAULT_NAMESPACE="knative-serving"
+export ISTIO_VERSION="stable"
+export UNINSTALL_LIST=()
+export TMP_DIR=$(mktemp -d -t ci-$(date +%Y-%m-%d-%H-%M-%S)-XXXXXXXXXX)
 
 function update_knative() {
-  local istio_version="istio-1.4-latest"
   # Mako needs to escape '.' in tags. Use '_' instead.
-  local istio_version_escaped=${istio_version//./_}
+  local istio_version_escaped=${ISTIO_VERSION//./_}
 
-  pushd .
-  cd ${GOPATH}/src/knative.dev
   echo ">> Update istio"
   # Some istio pods occasionally get overloaded and die, delete all deployments
   # and services from istio before reintalling it, to get them freshly recreated
   kubectl delete deployments --all -n istio-system
   kubectl delete services --all -n istio-system
-  kubectl apply -f serving/third_party/$istio_version/istio-crds.yaml || abort "Failed to apply istio-crds"
-  kubectl apply -f serving/third_party/$istio_version/istio-ci-no-mesh.yaml || abort "Failed to apply istio-ci-no-mesh"
+  install_istio || abort "Failed to install Istio"
 
   # Overprovision the Istio gateways and pilot.
   kubectl patch hpa -n istio-system istio-ingressgateway \
@@ -49,13 +54,12 @@ function update_knative() {
   local n=0
   until [ $n -ge 3 ]
   do
-    ko apply -f serving/config/ && break
+    ko apply -f config/ && break
     n=$[$n+1]
   done
   if [ $n == 3 ]; then
     abort "Failed to patch serving"
   fi
-  popd
 
   # Update the activator hpa minReplicas to 10
   kubectl patch hpa -n knative-serving activator \
diff --git a/test/upgrade/service_postupgrade_test.go b/test/upgrade/service_postupgrade_test.go
index 2c153a11c..5cdb81029 100644
--- a/test/upgrade/service_postupgrade_test.go
+++ b/test/upgrade/service_postupgrade_test.go
@@ -140,3 +140,17 @@ func TestCreateNewServicePostUpgrade(t *testing.T) {
 	t.Parallel()
 	createNewService(postUpgradeServiceName, t)
 }
+
+func TestInitialScalePostUpgrade(t *testing.T) {
+	t.Parallel()
+	clients := e2e.Setup(t)
+
+	t.Logf("Getting service %q", initialScaleServiceName)
+	svc, err := clients.ServingClient.Services.Get(initialScaleServiceName, metav1.GetOptions{})
+	if err != nil {
+		t.Fatal("Failed to get Service:", err)
+	}
+	if !svc.IsReady() {
+		t.Fatalf("Post upgrade Service is not ready with reason %q", svc.Status.GetCondition(v1.ServiceConditionRoutesReady).Reason)
+	}
+}
diff --git a/test/upgrade/service_preupgrade_test.go b/test/upgrade/service_preupgrade_test.go
index 95e73843e..03516d8cc 100644
--- a/test/upgrade/service_preupgrade_test.go
+++ b/test/upgrade/service_preupgrade_test.go
@@ -90,3 +90,20 @@ func TestBYORevisionPreUpgrade(t *testing.T) {
 		t.Fatal("Failed to create Service:", err)
 	}
 }
+
+func TestInitialScalePreUpgrade(t *testing.T) {
+	t.Parallel()
+	clients := e2e.Setup(t)
+	names := test.ResourceNames{
+		Service: initialScaleServiceName,
+		Image:   test.PizzaPlanet1,
+	}
+
+	resources, err := v1test.CreateServiceReady(t, clients, &names)
+	if err != nil {
+		t.Fatal("Failed to create Service:", err)
+	}
+	if err = e2e.WaitForScaleToZero(t, revisionresourcenames.Deployment(resources.Revision), clients); err != nil {
+		t.Fatal("Could not scale to zero:", err)
+	}
+}
diff --git a/test/upgrade/upgrade.go b/test/upgrade/upgrade.go
index eba410613..ff7723e89 100644
--- a/test/upgrade/upgrade.go
+++ b/test/upgrade/upgrade.go
@@ -41,6 +41,7 @@ const (
 	scaleToZeroServiceName   = "scale-to-zero-upgrade-service"
 	byoServiceName           = "byo-revision-name-upgrade-test"
 	byoRevName               = byoServiceName + "-" + "rev1"
+	initialScaleServiceName  = "init-scale-service"
 )
 
 // Shamelessly cribbed from conformance/service_test.
diff --git a/third_party/contour-latest/contour.yaml b/third_party/contour-latest/contour.yaml
index a24992d7b..d9db697a3 100644
--- a/third_party/contour-latest/contour.yaml
+++ b/third_party/contour-latest/contour.yaml
@@ -1432,7 +1432,7 @@ spec:
         # if we change this on each version, you can no longer upgrade
         # just by applying the deployment YAML.
         # See #2423, #2395, #2150, and #2030 for earlier questions about this.
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         command:
         - contour
@@ -1672,7 +1672,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:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         name: contour
         ports:
@@ -1764,7 +1764,7 @@ spec:
         args:
         - envoy
         - shutdown-manager
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         lifecycle:
           preStop:
@@ -1840,7 +1840,7 @@ spec:
         - --envoy-key-file=/certs/tls.key
         command:
         - contour
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         name: envoy-initconfig
         volumeMounts:
@@ -3305,7 +3305,7 @@ spec:
         # if we change this on each version, you can no longer upgrade
         # just by applying the deployment YAML.
         # See #2423, #2395, #2150, and #2030 for earlier questions about this.
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         command:
         - contour
@@ -3545,7 +3545,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:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         name: contour
         ports:
@@ -3637,7 +3637,7 @@ spec:
         args:
         - envoy
         - shutdown-manager
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         lifecycle:
           preStop:
@@ -3713,7 +3713,7 @@ spec:
         - --envoy-key-file=/certs/tls.key
         command:
         - contour
-        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4fb619dd7362dbee3339619b519e4803fe40983859964174c9e5e590d18e6d5b
+        image: gcr.io/knative-nightly/github.com/projectcontour/contour/cmd/contour@sha256:4cbd9afeb467115b89d341838a52fda369e7f991077611473479603e6bfc11b1
         imagePullPolicy: Always
         name: envoy-initconfig
         volumeMounts:
diff --git a/third_party/contour-latest/net-contour.yaml b/third_party/contour-latest/net-contour.yaml
index 0441d3b71..625a0897f 100644
--- a/third_party/contour-latest/net-contour.yaml
+++ b/third_party/contour-latest/net-contour.yaml
@@ -35,7 +35,7 @@ metadata:
   namespace: knative-serving
   labels:
     networking.knative.dev/ingress-provider: contour
-    serving.knative.dev/release: "v20200818-dcc1cb28"
+    serving.knative.dev/release: "v20200819-447288cb"
 data:
   _example: |
     ################################
@@ -100,7 +100,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:d3be1d1a17518cb1a22065a53195d23b76abb0550c73f1233a0b3c3943909194
+        image: gcr.io/knative-nightly/knative.dev/net-contour/cmd/controller@sha256:7a881b09e7f14d102e5cfb30979bb2477f6d64cb1eb35836e7124b770b55a236
         resources:
           requests:
             cpu: 40m
diff --git a/third_party/kourier-latest/kourier.yaml b/third_party/kourier-latest/kourier.yaml
index 2a7589f4c..31fb27efb 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -104,7 +104,7 @@ spec:
         app: 3scale-kourier-control
     spec:
       containers:
-      - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:f40cfd08cb6d27893c29e0114450fd4232950c7eb91b0c5313cd180f809bc281
+      - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:2106344934905a4957621611ae69383d8a186b9f3898e5c1e3c128af177a22e7
         imagePullPolicy: Always
         name: kourier-control
         env: