Repository: knative/serving
Pull request #7862 (2020-05-06 13:26:11)

Update autoscaler package doc comment
The autoscaler package doc comment was last updated in 2018 and refers to a no-longer-existing field `stableConcurrencyPerPod` and to a single-tenant mode, which also no longer exists :)

This updates it with some of @markusthoemmes's nice text from https://knative.dev/development/serving/configuring-autoscaling (which is a bit more generic so shouldn't go out of date so quickly).

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

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

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

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

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

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

Patch:
diff --git a/OWNERS_ALIASES b/OWNERS_ALIASES
index 4a3575e2e..7a301f00b 100644
--- a/OWNERS_ALIASES
+++ b/OWNERS_ALIASES
@@ -55,6 +55,7 @@ aliases:
   - yt3liu
 
   networking-approvers:
+  - JRBANCEL
   - markusthoemmes
   - mdemirhan
   - nak3
diff --git a/go.mod b/go.mod
index e39c93f7c..b565c5e76 100644
--- a/go.mod
+++ b/go.mod
@@ -43,9 +43,9 @@ require (
 	k8s.io/code-generator v0.18.0
 	k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
 	k8s.io/metrics v0.17.2
-	knative.dev/caching v0.0.0-20200505155344-08192258fa45
-	knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2
-	knative.dev/test-infra v0.0.0-20200505192244-75864c82db21
+	knative.dev/caching v0.0.0-20200505210444-cf277ae1c062
+	knative.dev/pkg v0.0.0-20200506001744-478962f05e2b
+	knative.dev/test-infra v0.0.0-20200506045344-e71b1288c15c
 )
 
 replace (
diff --git a/go.sum b/go.sum
index c27d0217c..3e1ceffed 100644
--- a/go.sum
+++ b/go.sum
@@ -1430,8 +1430,8 @@ k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl
 k8s.io/utils v0.0.0-20200124190032-861946025e34 h1:HjlUD6M0K3P8nRXmr2B9o4F9dUy9TCj/aEpReeyi6+k=
 k8s.io/utils v0.0.0-20200124190032-861946025e34/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
 knative.dev/caching v0.0.0-20190719140829-2032732871ff/go.mod h1:dHXFU6CGlLlbzaWc32g80cR92iuBSpsslDNBWI8C7eg=
-knative.dev/caching v0.0.0-20200505155344-08192258fa45 h1:9J+40v7Lg2NX0PijRBJDdKYoUMvEi36DyA4MduRRqNU=
-knative.dev/caching v0.0.0-20200505155344-08192258fa45/go.mod h1:5yMSCQ8YSPZPqaK05el6YJcEnM1EyLyvu1V41w5fPS0=
+knative.dev/caching v0.0.0-20200505210444-cf277ae1c062 h1:BFAKZcMjSuczpr1biMbEumIEGXI0AkvsZ9PilrGEh2A=
+knative.dev/caching v0.0.0-20200505210444-cf277ae1c062/go.mod h1:cULFZCx2QuhZYr1YRaUa5PO5ZPRRXeipE2uIKyAojJ8=
 knative.dev/eventing-contrib v0.6.1-0.20190723221543-5ce18048c08b/go.mod h1:SnXZgSGgMSMLNFTwTnpaOH7hXDzTFtw0J8OmHflNx3g=
 knative.dev/pkg v0.0.0-20191101194912-56c2594e4f11/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
 knative.dev/pkg v0.0.0-20191111150521-6d806b998379/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
@@ -1439,12 +1439,16 @@ knative.dev/pkg v0.0.0-20200428194351-90fc61bae7f7/go.mod h1:o+e8OVEJKIuvXPsGVPI
 knative.dev/pkg v0.0.0-20200504180943-4a2ba059b008/go.mod h1:1RvwKBbKqKYt5rgI4lfYdWCdtXgMxJY73QxPb3jZPC4=
 knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2 h1:Qu2NlOHb9p3g+CSL/ok9+FySowN60URFEKRSXfWtDv4=
 knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2/go.mod h1:Q6sL35DdGs8hIQZKdaCXJGgY8f90BmNBKSb8z6d/BTM=
+knative.dev/pkg v0.0.0-20200506001744-478962f05e2b h1:SFCuEj+NeA8dVn4Ms1ymfF4FUru8jc7D56L17Co1qe8=
+knative.dev/pkg v0.0.0-20200506001744-478962f05e2b/go.mod h1:9UQS6bJECqqFG0q9BPaATbcG78co0s9Q6Dzo/6mR4uI=
 knative.dev/test-infra v0.0.0-20200407185800-1b88cb3b45a5/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ=
 knative.dev/test-infra v0.0.0-20200430225942-f7c1fafc1cde h1:QSzxFsf21WXNhODvh0jRKbFR+c5UI7WFjiISy/sMOLg=
 knative.dev/test-infra v0.0.0-20200430225942-f7c1fafc1cde/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ=
 knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxPZ20keR2zCNtiQA1MP9ZB4BH4HuI+SIU=
 knative.dev/test-infra v0.0.0-20200505192244-75864c82db21 h1:SsvqMKpvrn7cl7UqRUIT90SXDowHzpzHwHaTu+wN70s=
 knative.dev/test-infra v0.0.0-20200505192244-75864c82db21/go.mod h1:AqweEMgaMbb2xmYq9ZOPsH/lQ61qNx2XGr5tGltj5QU=
+knative.dev/test-infra v0.0.0-20200506045344-e71b1288c15c h1:GfRICwJBY2VmbzFzu/se73+gsfKEkc83qlTBcohJvN0=
+knative.dev/test-infra v0.0.0-20200506045344-e71b1288c15c/go.mod h1:aMif0KXL4g19YCYwsy4Ocjjz5xgPlseYV+B95Oo4JGE=
 modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
diff --git a/pkg/autoscaler/config/config.go b/pkg/autoscaler/config/config.go
index 60f61a3e1..ef7ce251e 100644
--- a/pkg/autoscaler/config/config.go
+++ b/pkg/autoscaler/config/config.go
@@ -237,8 +237,9 @@ func validate(lc *Config) (*Config, error) {
 	if lc.ScaleToZeroGracePeriod < autoscaling.WindowMin {
 		return nil, fmt.Errorf("scale-to-zero-grace-period must be at least %v, got %v", autoscaling.WindowMin, lc.ScaleToZeroGracePeriod)
 	}
+
 	if lc.TargetBurstCapacity < 0 && lc.TargetBurstCapacity != -1 {
-		return nil, fmt.Errorf("target-burst-capacity must be non-negative, got %f", lc.TargetBurstCapacity)
+		return nil, fmt.Errorf("target-burst-capacity must be either non-negative or -1 (for unlimited), got %f", lc.TargetBurstCapacity)
 	}
 
 	if lc.ContainerConcurrencyTargetFraction <= 0 || lc.ContainerConcurrencyTargetFraction > 1 {
diff --git a/pkg/autoscaler/doc.go b/pkg/autoscaler/doc.go
index 2310795f1..4fc4f9f13 100644
--- a/pkg/autoscaler/doc.go
+++ b/pkg/autoscaler/doc.go
@@ -15,25 +15,7 @@ limitations under the License.
 */
 
 /*
-Package autoscaler calculates the number of pods necessary for the
-desired level of concurrency per pod (stableConcurrencyPerPod). It
-operates in two modes, stable mode and panic mode.
-
-Stable mode calculates the average concurrency observed over the last
-60 seconds and adjusts the observed pod count to achieve the target
-value. Current observed pod count is the number of unique pod names
-which show up in the last 60 seconds.
-
-Panic mode calculates the average concurrency observed over the last 6
-seconds and adjusts the observed pod count to achieve the stable
-target value. Panic mode is engaged when the observed 6 second average
-concurrency reaches 2x the target stable concurrency. Panic mode will
-last at least 60 seconds--longer if the 2x threshold is repeatedly
-breached. During panic mode the number of pods is never decreased in
-order to prevent flapping.
-
-Package autoscaler supports both single-tenant (one autoscaler per
-revision) and multitenant (one autoscaler for all revisions) autoscalers;
-config/controller.yaml determines which kind of autoscaler is used.
+Package autoscaler calculates the number of pods necessary for the desired
+level of concurrency per pod.
 */
 package autoscaler
diff --git a/pkg/autoscaler/scaling/autoscaler.go b/pkg/autoscaler/scaling/autoscaler.go
index 5372ca85b..cf1b71f5d 100644
--- a/pkg/autoscaler/scaling/autoscaler.go
+++ b/pkg/autoscaler/scaling/autoscaler.go
@@ -47,9 +47,7 @@ type Autoscaler struct {
 	lister       corev1listers.EndpointsLister
 	reporterCtx  context.Context
 
-	// State in panic mode. Carries over multiple Scale calls. Guarded
-	// by the stateMux.
-	stateMux     sync.Mutex
+	// State in panic mode.
 	panicTime    time.Time
 	maxPanicPods int32
 
@@ -129,6 +127,8 @@ func (a *Autoscaler) Update(deciderSpec *DeciderSpec) error {
 // Scale calculates the desired scale based on current statistics given the current time.
 // desiredPodCount is the calculated pod count the autoscaler would like to set.
 // validScale signifies whether the desiredPodCount should be applied or not.
+// Scale is not thread safe in regards to panic state, but it's thread safe in
+// regards to acquiring the decider spec.
 func (a *Autoscaler) Scale(ctx context.Context, now time.Time) ScaleResult {
 	logger := logging.FromContext(ctx)
 
@@ -195,8 +195,6 @@ func (a *Autoscaler) Scale(ctx context.Context, now time.Time) ScaleResult {
 
 	isOverPanicThreshold := dppc/readyPodsCount >= spec.PanicThreshold
 
-	a.stateMux.Lock()
-	defer a.stateMux.Unlock()
 	if a.panicTime.IsZero() && isOverPanicThreshold {
 		// Begin panicking when we cross the threshold in the panic window.
 		logger.Info("PANICKING.")
diff --git a/third_party/net-istio.yaml b/third_party/net-istio.yaml
index a53fc2fc5..6459924cd 100644
--- a/third_party/net-istio.yaml
+++ b/third_party/net-istio.yaml
@@ -18,7 +18,7 @@ metadata:
   # These are the permissions needed by the Istio Ingress implementation.
   name: knative-serving-istio
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
     serving.knative.dev/controller: "true"
     networking.knative.dev/ingress-provider: istio
 rules:
@@ -48,7 +48,7 @@ metadata:
   name: knative-ingress-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -85,7 +85,7 @@ metadata:
   name: cluster-local-gateway
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -118,7 +118,7 @@ kind: MutatingWebhookConfiguration
 metadata:
   name: webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
 webhooks:
 - admissionReviewVersions:
   - v1beta1
@@ -153,7 +153,7 @@ kind: ValidatingWebhookConfiguration
 metadata:
   name: config.webhook.istio.networking.internal.knative.dev
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
 webhooks:
 - admissionReviewVersions:
   - v1beta1
@@ -190,7 +190,7 @@ metadata:
   name: istio-webhook-certs
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
 
 ---
 # Copyright 2018 The Knative Authors
@@ -213,7 +213,7 @@ metadata:
   name: config-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
     networking.knative.dev/ingress-provider: istio
 data:
   _example: |
@@ -283,7 +283,7 @@ metadata:
   name: networking-istio
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
     networking.knative.dev/ingress-provider: istio
 spec:
   selector:
@@ -299,14 +299,14 @@ spec:
         sidecar.istio.io/inject: "false"
       labels:
         app: networking-istio
-        serving.knative.dev/release: "v20200505-b8df251"
+        serving.knative.dev/release: "v20200506-9851311"
     spec:
       serviceAccountName: controller
       containers:
       - name: networking-istio
         # This is the Go import path for the binary that is containerized
         # and substituted here.
-        image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:c72b2b576bdecf6ac47a6c8219499c2955a16a2128569e83991bd8c6c61eed0f
+        image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/controller@sha256:d094ac0ff72940fb83bcb25d613970ba283a913526241a067ffb9326577380a5
         resources:
           requests:
             cpu: 30m
@@ -358,7 +358,7 @@ metadata:
   name: istio-webhook
   namespace: knative-serving
   labels:
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
 spec:
   selector:
     matchLabels:
@@ -371,14 +371,14 @@ spec:
       labels:
         app: istio-webhook
         role: istio-webhook
-        serving.knative.dev/release: "v20200505-b8df251"
+        serving.knative.dev/release: "v20200506-9851311"
     spec:
       serviceAccountName: controller
       containers:
       - name: webhook
         # This is the Go import path for the binary that is containerized
         # and substituted here.
-        image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:1b7e192b5a8d3182a16776de5d4bfca9131261840b3d2dbea672b38409cfb329
+        image: gcr.io/knative-nightly/knative.dev/net-istio/cmd/webhook@sha256:ebfc4570445c0c0382e0e1757cae319c07fa8d7949562c33f6db73a259486b4e
         resources:
           requests:
             cpu: 20m
@@ -432,7 +432,7 @@ metadata:
   namespace: knative-serving
   labels:
     role: istio-webhook
-    serving.knative.dev/release: "v20200505-b8df251"
+    serving.knative.dev/release: "v20200506-9851311"
 spec:
   ports:
   - # Define metrics and profiling for them to be accessible within service meshes.
diff --git a/vendor/knative.dev/pkg/apis/duck/v1/kresource_type.go b/vendor/knative.dev/pkg/apis/duck/v1/kresource_type.go
index 7ea2d70c9..b64977fcb 100644
--- a/vendor/knative.dev/pkg/apis/duck/v1/kresource_type.go
+++ b/vendor/knative.dev/pkg/apis/duck/v1/kresource_type.go
@@ -33,6 +33,8 @@ type KRShaped interface {
 	GetTypeMeta() *metav1.TypeMeta
 
 	GetStatus() *Status
+
+	GetTopLevelConditionType() apis.ConditionType
 }
 
 // Asserts KResource conformance with KRShaped
@@ -88,3 +90,13 @@ func (t *KResource) GetTypeMeta() *metav1.TypeMeta {
 func (t *KResource) GetStatus() *Status {
 	return &t.Status
 }
+
+// GetTopLevelConditionType retrieves the happy condition of this resource. Implements the KRShaped interface.
+func (t *KResource) GetTopLevelConditionType() apis.ConditionType {
+	// Note: KResources are unmarshalled from existing resources. This will only work properly for resources that
+	// have already been initialized to their type.
+	if cond := t.Status.GetCondition(apis.ConditionSucceeded); cond != nil {
+		return apis.ConditionSucceeded
+	}
+	return apis.ConditionReady
+}
diff --git a/vendor/knative.dev/pkg/hack/generate-knative.sh b/vendor/knative.dev/pkg/hack/generate-knative.sh
index cbd957077..931e0a425 100644
--- a/vendor/knative.dev/pkg/hack/generate-knative.sh
+++ b/vendor/knative.dev/pkg/hack/generate-knative.sh
@@ -46,13 +46,6 @@ APIS_PKG="$3"
 GROUPS_WITH_VERSIONS="$4"
 shift 4
 
-(
-  # To support running this script from anywhere, we have to first cd into this directory
-  # so we can install the tools.
-  cd $(dirname "${0}")
-  go install ../codegen/cmd/injection-gen
-)
-
 function codegen::join() { local IFS="$1"; shift; echo "$*"; }
 
 # enumerate group versions
@@ -89,7 +82,7 @@ if grep -qw "injection" <<<"${GENS}"; then
   # Clear old injection
   rm -rf ${OUTPUT_PKG}
 
-  ${GOPATH}/bin/injection-gen \
+  go run knative.dev/pkg/codegen/cmd/injection-gen \
     --input-dirs $(codegen::join , "${FQ_APIS[@]}") \
     --versioned-clientset-package ${VERSIONED_CLIENTSET_PKG} \
     --external-versions-informers-package ${EXTERNAL_INFORMER_PKG} \
diff --git a/vendor/knative.dev/pkg/hack/update-codegen.sh b/vendor/knative.dev/pkg/hack/update-codegen.sh
index 108d8e646..d049c42cb 100644
--- a/vendor/knative.dev/pkg/hack/update-codegen.sh
+++ b/vendor/knative.dev/pkg/hack/update-codegen.sh
@@ -24,8 +24,6 @@ source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/library.sh
 
 CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${REPO_ROOT_DIR}; ls -d -1 $(dirname $0)/../vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
 
-go install $(dirname $0)/../vendor/k8s.io/code-generator/cmd/deepcopy-gen
-
 # generate the code with:
 # --output-base    because this script should also be able to run inside the vendor dir of
 #                  k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
@@ -64,7 +62,7 @@ ${CODEGEN_PKG}/generate-groups.sh "deepcopy" \
   --go-header-file ${REPO_ROOT_DIR}/hack/boilerplate/boilerplate.go.txt
 
 # Depends on generate-groups.sh to install bin/deepcopy-gen
-${GOPATH}/bin/deepcopy-gen --input-dirs \
+go run k8s.io/code-generator/cmd/deepcopy-gen  --input-dirs \
   $(echo \
   knative.dev/pkg/apis \
   knative.dev/pkg/tracker \
diff --git a/vendor/modules.txt b/vendor/modules.txt
index af091856a..ff2b720c9 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1147,7 +1147,7 @@ k8s.io/utils/integer
 k8s.io/utils/path
 k8s.io/utils/pointer
 k8s.io/utils/trace
-# knative.dev/caching v0.0.0-20200505155344-08192258fa45
+# knative.dev/caching v0.0.0-20200505210444-cf277ae1c062
 ## explicit
 knative.dev/caching/config
 knative.dev/caching/pkg/apis/caching
@@ -1168,7 +1168,7 @@ knative.dev/caching/pkg/client/injection/informers/caching/v1alpha1/image/fake
 knative.dev/caching/pkg/client/injection/informers/factory
 knative.dev/caching/pkg/client/injection/informers/factory/fake
 knative.dev/caching/pkg/client/listers/caching/v1alpha1
-# knative.dev/pkg v0.0.0-20200505191044-3da93ebb24c2
+# knative.dev/pkg v0.0.0-20200506001744-478962f05e2b
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate
@@ -1280,7 +1280,7 @@ knative.dev/pkg/webhook/resourcesemantics/conversion
 knative.dev/pkg/webhook/resourcesemantics/defaulting
 knative.dev/pkg/webhook/resourcesemantics/validation
 knative.dev/pkg/websocket
-# knative.dev/test-infra v0.0.0-20200505192244-75864c82db21
+# knative.dev/test-infra v0.0.0-20200506045344-e71b1288c15c
 ## explicit
 knative.dev/test-infra/scripts
 # sigs.k8s.io/structured-merge-diff v1.0.1


Test patch:
diff --git a/vendor/knative.dev/test-infra/scripts/e2e-tests.sh b/vendor/knative.dev/test-infra/scripts/e2e-tests.sh
index 917f5ebf9..01b2d0e40 100644
--- a/vendor/knative.dev/test-infra/scripts/e2e-tests.sh
+++ b/vendor/knative.dev/test-infra/scripts/e2e-tests.sh
@@ -167,11 +167,11 @@ function resolve_k8s_version() {
   local gke_versions=($(echo -n "${versions//;/ }"))
   echo "Available GKE versions in $2 are [${versions//;/, }]"
   if [[ "${target_version}" == "gke-latest" ]]; then
-    # Get first (latest) version, excluding the "-gke.#" suffix
+    # Get first (latest) version
     E2E_CLUSTER_VERSION="${gke_versions[0]}"
     echo "Using latest version, ${E2E_CLUSTER_VERSION}"
   else
-    local latest="$(echo "${gke_versions[@]}" | tr ' ' '\n' | grep -E ^${target_version} | cut -f1 -d- | sort | tail -1)"
+    local latest="$(echo "${gke_versions[@]}" | tr ' ' '\n' | grep -E ^${target_version} | sort -V | tail -1)"
     if [[ -z "${latest}" ]]; then
       echo "ERROR: version ${target_version} is not available"
       return 1
diff --git a/vendor/knative.dev/test-infra/scripts/library.sh b/vendor/knative.dev/test-infra/scripts/library.sh
index 34e9c6aa6..7933cc8b8 100644
--- a/vendor/knative.dev/test-infra/scripts/library.sh
+++ b/vendor/knative.dev/test-infra/scripts/library.sh
@@ -389,25 +389,8 @@ function mktemp_with_extension() {
 #             $2 - check name as an identifier (e.g., GoBuild)
 #             $3 - failure message (can contain newlines), optional (means success)
 function create_junit_xml() {
-  local xml="$(mktemp_with_extension ${ARTIFACTS}/junit_XXXXXXXX xml)"
-  local failure=""
-  if [[ "$3" != "" ]]; then
-    # Transform newlines into HTML code.
-    # Also escape `<` and `>` as here: https://github.com/golang/go/blob/50bd1c4d4eb4fac8ddeb5f063c099daccfb71b26/src/encoding/json/encode.go#L48,
-    # this is temporary solution for fixing https://github.com/knative/test-infra/issues/1204,
-    # which should be obsolete once Test-infra 2.0 is in place
-    local msg="$(echo -n "$3" | sed 's/$/\&#xA;/g' | sed 's/</\\u003c/' | sed 's/>/\\u003e/' | sed 's/&/\\u0026/' | tr -d '\n')"
-    failure="<failure message=\"Failed\" type=\"\">${msg}</failure>"
-  fi
-  cat << EOF > "${xml}"
-<testsuites>
-	<testsuite tests="1" failures="1" time="0.000" name="$1">
-		<testcase classname="" name="$2" time="0.0">
-			${failure}
-		</testcase>
-	</testsuite>
-</testsuites>
-EOF
+  local xml="$(mktemp_with_extension "${ARTIFACTS}"/junit_XXXXXXXX xml)"
+  run_kntest junit --suite="$1" --name="$2" --err-msg="$3" --dest="${xml}" || return 1
 }
 
 # Runs a go test and generate a junit summary.
@@ -515,31 +498,43 @@ function start_latest_knative_eventing() {
 #             $3..$n - parameters passed to the tool.
 function run_go_tool() {
   local tool=$2
-  local action=get
-  [[ $1 =~ ^[\./].* ]] && action=install
-  # Avoid running `go get` from root dir of the repository, as it can change go.sum and go.mod files.
-  # See discussions in https://github.com/golang/go/issues/27643.
-  if [[ -z "$(which ${tool})" ]]; then
-    local action=get
-    [[ $1 =~ ^[\./].* ]] && action=install
+  local install_failed=0
+  local action="get"
+  [[ $1 =~ ^[\./].* ]] && action="install"
+  # Install the tool in the following situations:
+  #   - The tool does not exist.
+  #   - The tool needs to be installed from a local path.
+  #   - Version of the tool is specificied in the given tool path.
+  # TODO(chizhg): derive a better versioning story for the tools being used.
+  if [[ -z "$(which "${tool}")" || "${action}" == "install" || "${tool}" =~ "@" ]]; then
     # Avoid running `go get` from root dir of the repository, as it can change go.sum and go.mod files.
     # See discussions in https://github.com/golang/go/issues/27643.
     if [[ ${action} == "get" && $(pwd) == "${REPO_ROOT_DIR}" ]]; then
       local temp_dir="$(mktemp -d)"
-      local install_failed=0
       # Swallow the output as we are returning the stdout in the end.
       pushd "${temp_dir}" > /dev/null 2>&1
       GOFLAGS="" go ${action} $1 || install_failed=1
       popd > /dev/null 2>&1
-      (( install_failed )) && return ${install_failed}
     else
-      GOFLAGS="" go ${action} $1
+      GOFLAGS="" go ${action} $1 || install_failed=1
     fi
   fi
+  (( install_failed )) && return ${install_failed}
   shift 2
   ${tool} "$@"
 }
 
+# Run "kntest" tool
+# Parameters: $1..$n - parameters passed to the tool
+function run_kntest() {
+  if [[ "${REPO_NAME}" == "test-infra" ]]; then
+    go run "${REPO_ROOT_DIR}"/kntest/cmd/kntest "$@"
+  else
+    # Always run the latest version.
+    run_go_tool knative.dev/test-infra/kntest/cmd/kntest@master "$@"
+  fi
+}
+
 # Run go-licenses to update licenses.
 # Parameters: $1 - output file, relative to repo root dir.
 #             $2 - directory to inspect.