Repository: knative/serving
Pull request #8183 (2020-06-03 14:19:32)

[master] Auto-update dependencies
<!--[master] Auto-update dependencies-->
<!---->
Produced via:
  `./hack/update-deps.sh --upgrade && ./hack/update-codegen.sh`
/assign dprotaso vagababov
/cc dprotaso vagababov


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

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

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

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":[]} -->

Patch:
diff --git a/go.mod b/go.mod
index f4d3a070d..7773514f3 100644
--- a/go.mod
+++ b/go.mod
@@ -43,8 +43,8 @@ require (
 	k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
 	k8s.io/metrics v0.17.6
 	knative.dev/caching v0.0.0-20200521155757-e78d17bc250e
-	knative.dev/pkg v0.0.0-20200528190300-08a86da47d28
-	knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e
+	knative.dev/pkg v0.0.0-20200603004717-9d862737e5c1
+	knative.dev/test-infra v0.0.0-20200602194317-2a31597e0f46
 )
 
 // pin the older grpc - see: https://github.com/grpc/grpc-go/issues/3180
diff --git a/go.sum b/go.sum
index 4feb2f05d..d4f70f75c 100644
--- a/go.sum
+++ b/go.sum
@@ -1319,10 +1319,9 @@ knative.dev/pkg v0.0.0-20200515002500-16d7b963416f/go.mod h1:tMOHGbxtRz8zYFGEGpV
 knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7 h1:9S2r59HZJF9nKvoRLg5zJzx6XpVlVyvVRqz/C/h6h2s=
 knative.dev/pkg v0.0.0-20200519155757-14eb3ae3a5a7/go.mod h1:QgNZTxnwpB/oSpNcfnLVlw+WpEwwyKAvJlvR3hgeltA=
 knative.dev/pkg v0.0.0-20200520073958-94316e20e860/go.mod h1:QgNZTxnwpB/oSpNcfnLVlw+WpEwwyKAvJlvR3hgeltA=
-knative.dev/pkg v0.0.0-20200527024749-495174c96651 h1:/LhCktTMhJrCDXGg3KCWeSQTLLGy3Ms4AaqM9O/05dI=
-knative.dev/pkg v0.0.0-20200527024749-495174c96651/go.mod h1:4ipprwHqpqiyYHbrEjSf1kNwL+sJOqHhj1ujO2WxvpE=
-knative.dev/pkg v0.0.0-20200528190300-08a86da47d28 h1:tLWWfrpGYT8vs/QLWYc7s0pqaw+ISz4UmM9AhrWBc8o=
-knative.dev/pkg v0.0.0-20200528190300-08a86da47d28/go.mod h1:ywZfX/0D8hoOf4uJVgeEvJpSmsOauQvr1IuAWld9UjM=
+knative.dev/pkg v0.0.0-20200601184204-18c577c87d4f/go.mod h1:ywZfX/0D8hoOf4uJVgeEvJpSmsOauQvr1IuAWld9UjM=
+knative.dev/pkg v0.0.0-20200603004717-9d862737e5c1 h1:RdPH0bgm61DQ/azXkQq04pwFnaHH9xSL5yJ9+X2nuiQ=
+knative.dev/pkg v0.0.0-20200603004717-9d862737e5c1/go.mod h1:8IfPj/lpuKHHg82xZCl2wuFZ3BM96To72sN1W8T9wjQ=
 knative.dev/test-infra v0.0.0-20200407185800-1b88cb3b45a5/go.mod h1:xcdUkMJrLlBswIZqL5zCuBFOC22WIPMQoVX1L35i0vQ=
 knative.dev/test-infra v0.0.0-20200505052144-5ea2f705bb55/go.mod h1:WqF1Azka+FxPZ20keR2zCNtiQA1MP9ZB4BH4HuI+SIU=
 knative.dev/test-infra v0.0.0-20200513011557-d03429a76034 h1:JxqONCZVS7or+Fv3ebVQoipuIBH7Ig3Qbx170hgIF+A=
@@ -1333,8 +1332,8 @@ knative.dev/test-infra v0.0.0-20200519161858-554a95a37986 h1:ZDy43jkWPQ75d4l4DGy
 knative.dev/test-infra v0.0.0-20200519161858-554a95a37986/go.mod h1:LeNa1Wvn47efeQUkpkn3XG7Fx9Ga+rhAP13SZyjaEGg=
 knative.dev/test-infra v0.0.0-20200522180958-6a0a9b9d893a h1:c0qTABRcNoxZVu5gsryLWPZtGa/s4zsvovz0nGefuzg=
 knative.dev/test-infra v0.0.0-20200522180958-6a0a9b9d893a/go.mod h1:n9eQkzmSNj8BiqNFl1lzoz68D09uMeJfyOjc132Gbik=
-knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e h1:ZzmzPgCKdrFg2MA2sGtd9HrlIQ7XidnmMJB8RDEduO0=
-knative.dev/test-infra v0.0.0-20200528222301-350178ab2a0e/go.mod h1:7JtOmoYiYxh2oFO23nwGanuJ6qT6mFrRlZV1LL6gomY=
+knative.dev/test-infra v0.0.0-20200602194317-2a31597e0f46 h1:xXewx8AeTeNKIsqUwUJ24RF0xOVm3EQ0t7vBmM+RgB4=
+knative.dev/test-infra v0.0.0-20200602194317-2a31597e0f46/go.mod h1:JV4E61erdHLn4jT0X+svUP7lZYggJyXMCGDewTSQuO8=
 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/vendor/knative.dev/pkg/configmap/example.go b/vendor/knative.dev/pkg/configmap/example.go
new file mode 100644
index 000000000..ee17666b7
--- /dev/null
+++ b/vendor/knative.dev/pkg/configmap/example.go
@@ -0,0 +1,34 @@
+/*
+Copyright 2020 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package configmap
+
+import (
+	"hash/crc32"
+)
+
+const (
+	// ExampleKey signifies a given example configuration in a ConfigMap.
+	ExampleKey = "_example"
+
+	// ExampleChecksumLabel is the label that stores the computed checksum.
+	ExampleChecksumLabel = "knative.dev/example-checksum"
+)
+
+// Checksum generates a checksum for the example value to be compared against a respective label.
+func Checksum(value string) uint32 {
+	return crc32.ChecksumIEEE([]byte(value))
+}
diff --git a/vendor/knative.dev/pkg/configmap/store.go b/vendor/knative.dev/pkg/configmap/store.go
index a994601ab..ee643311b 100644
--- a/vendor/knative.dev/pkg/configmap/store.go
+++ b/vendor/knative.dev/pkg/configmap/store.go
@@ -23,9 +23,6 @@ import (
 	corev1 "k8s.io/api/core/v1"
 )
 
-// ExampleKey signifies a given example configuration in a ConfigMap.
-const ExampleKey = "_example"
-
 // Logger is the interface that UntypedStore expects its logger to conform to.
 // UntypedStore will log when updates succeed or fail.
 type Logger interface {
diff --git a/vendor/knative.dev/pkg/controller/controller.go b/vendor/knative.dev/pkg/controller/controller.go
index 15496b8a9..3981c5820 100644
--- a/vendor/knative.dev/pkg/controller/controller.go
+++ b/vendor/knative.dev/pkg/controller/controller.go
@@ -18,6 +18,7 @@ package controller
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"sync"
 	"time"
@@ -448,7 +449,7 @@ func (c *Impl) processNextWorkItem() bool {
 func (c *Impl) handleErr(err error, key types.NamespacedName) {
 	c.logger.Errorw("Reconcile error", zap.Error(err))
 
-	// Re-queue the key if it's an transient error.
+	// Re-queue the key if it's a transient error.
 	// We want to check that the queue is shutting down here
 	// since controller Run might have exited by now (since while this item was
 	// being processed, queue.Len==0).
@@ -483,8 +484,8 @@ func (c *Impl) FilteredGlobalResync(f func(interface{}) bool, si cache.SharedInf
 }
 
 // NewPermanentError returns a new instance of permanentError.
-// Users can wrap an error as permanentError with this in reconcile,
-// when he does not expect the key to get re-queued.
+// Users can wrap an error as permanentError with this in reconcile
+// when they do not expect the key to get re-queued.
 func NewPermanentError(err error) error {
 	return permanentError{e: err}
 }
@@ -495,16 +496,21 @@ type permanentError struct {
 	e error
 }
 
-// IsPermanentError returns true if given error is permanentError
+// IsPermanentError returns true if the given error is a permanentError or
+// wraps a permanentError.
 func IsPermanentError(err error) bool {
-	switch err.(type) {
-	case permanentError:
-		return true
-	default:
-		return false
-	}
+	return errors.Is(err, permanentError{})
+}
+
+// Is implements the Is() interface of error. It returns whether the target
+// error can be treated as equivalent to a permanentError.
+func (permanentError) Is(target error) bool {
+	_, ok := target.(permanentError)
+	return ok
 }
 
+var _ error = permanentError{}
+
 // Error implements the Error() interface of error.
 func (err permanentError) Error() string {
 	if err.e == nil {
@@ -514,6 +520,12 @@ func (err permanentError) Error() string {
 	return err.e.Error()
 }
 
+// Unwrap implements the Unwrap() interface of error. It returns the error
+// wrapped inside permanentError.
+func (err permanentError) Unwrap() error {
+	return err.e
+}
+
 // Informer is the group of methods that a type must implement to be passed to
 // StartInformers.
 type Informer interface {
diff --git a/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go b/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go
index 87bb722a2..e4c2d08dc 100644
--- a/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go
+++ b/vendor/knative.dev/pkg/metrics/stackdriver_exporter.go
@@ -102,10 +102,13 @@ func init() {
 
 func newOpencensusSDExporter(o stackdriver.Options) (view.Exporter, error) {
 	e, err := stackdriver.NewExporter(o)
-	if err == nil {
-		// Start the exporter.
-		// TODO(https://github.com/knative/pkg/issues/866): Move this to an interface.
-		e.StartMetricsExporter()
+	if err != nil {
+		return nil, err
+	}
+	// Start the exporter.
+	// TODO(https://github.com/knative/pkg/issues/866): Move this to an interface.
+	if err := e.StartMetricsExporter(); err != nil {
+		return nil, err
 	}
 	return e, nil
 }
diff --git a/vendor/knative.dev/pkg/reconciler/reconcile_common.go b/vendor/knative.dev/pkg/reconciler/reconcile_common.go
index cc0e2d712..6a32c06f7 100644
--- a/vendor/knative.dev/pkg/reconciler/reconcile_common.go
+++ b/vendor/knative.dev/pkg/reconciler/reconcile_common.go
@@ -32,6 +32,8 @@ func PreProcessReconcile(ctx context.Context, resource duckv1.KRShaped) {
 	if newStatus.ObservedGeneration != resource.GetGeneration() {
 		condSet := resource.GetConditionSet()
 		manager := condSet.Manage(newStatus)
+		// Ensure conditions are initialized before we modify.
+		manager.InitializeConditions()
 
 		// Reset Ready/Successful to unknown. The reconciler is expected to overwrite this.
 		manager.MarkUnknown(condSet.GetTopLevelConditionType(), failedGenerationBump, "unsuccessfully observed a new generation")
diff --git a/vendor/knative.dev/pkg/webhook/configmaps/configmaps.go b/vendor/knative.dev/pkg/webhook/configmaps/configmaps.go
index 8a3cd693c..8cc150b0a 100644
--- a/vendor/knative.dev/pkg/webhook/configmaps/configmaps.go
+++ b/vendor/knative.dev/pkg/webhook/configmaps/configmaps.go
@@ -184,6 +184,15 @@ func (ac *reconciler) validate(ctx context.Context, req *admissionv1beta1.Admiss
 		}
 	}
 
+	exampleData, hasExampleData := newObj.Data[configmap.ExampleKey]
+	exampleChecksum, hasExampleChecksumLabel := newObj.Labels[configmap.ExampleChecksumLabel]
+	if hasExampleData && hasExampleChecksumLabel &&
+		exampleChecksum != fmt.Sprint(configmap.Checksum(exampleData)) {
+		return fmt.Errorf(
+			"%q modified, you likely wanted to create an unindented configuration",
+			configmap.ExampleKey)
+	}
+
 	var err error
 	if constructor, ok := ac.constructors[newObj.Name]; ok {
 
diff --git a/vendor/knative.dev/pkg/webhook/webhook.go b/vendor/knative.dev/pkg/webhook/webhook.go
index ef7c238da..869269b46 100644
--- a/vendor/knative.dev/pkg/webhook/webhook.go
+++ b/vendor/knative.dev/pkg/webhook/webhook.go
@@ -73,13 +73,6 @@ const (
 	Connect Operation = admissionv1beta1.Connect
 )
 
-var (
-	// GracePeriod is the duration that the webhook will wait after it's
-	// context is cancelled (and probes are failing) before shutting down
-	// the http server.
-	GracePeriod = 30 * time.Second
-)
-
 // Webhook implements the external webhook for validation of
 // resources and configuration.
 type Webhook struct {
@@ -145,7 +138,7 @@ func New(
 		Logger:       logger,
 		synced:       cancel,
 		stopCh:       make(chan struct{}),
-		gracePeriod:  GracePeriod,
+		gracePeriod:  network.DefaultDrainTimeout,
 	}
 
 	webhook.mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0bdbfa660..77f1cc7f8 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1197,7 +1197,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-20200528190300-08a86da47d28
+# knative.dev/pkg v0.0.0-20200603004717-9d862737e5c1
 ## explicit
 knative.dev/pkg/apiextensions/storageversion
 knative.dev/pkg/apiextensions/storageversion/cmd/migrate
@@ -1313,7 +1313,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-20200528222301-350178ab2a0e
+# knative.dev/test-infra v0.0.0-20200602194317-2a31597e0f46
 ## explicit
 knative.dev/test-infra/scripts
 # sigs.k8s.io/structured-merge-diff/v2 v2.0.1


Test patch:
diff --git a/test/conformance/certificate/README.md b/test/conformance/certificate/README.md
new file mode 100644
index 000000000..063616e41
--- /dev/null
+++ b/test/conformance/certificate/README.md
@@ -0,0 +1,32 @@
+# Certificate Conformance Testing
+
+## Adding a test
+
+Tests need to be exported and accessible downstream so they should be placed in
+non-test files (ie. sometest.go). Additionally, invoke your test in the default
+`RunConformance` function in [`run.go`](./http01/run.go). This function is the
+entry point by which tests are executed.
+
+This approach aims to reduce the changes required when tests are added &
+removed.
+
+## Running the tests downstream
+
+To run all the conformance tests in your own repo we encourage adopting the
+[`RunConformance`](./http01/run.go) function to run all your tests.
+
+To do so would look something like:
+
+```go
+package conformance
+
+import (
+	"testing"
+	"knative.dev/serving/test/conformance/certificate/http01"
+)
+
+func TestYourHTTP01ProviderConformance(t *testing.T) {
+	http01.RunConformance(t)
+}
+
+```
diff --git a/test/conformance/ingress/README.md b/test/conformance/ingress/README.md
index b7573088e..5867ea8dc 100644
--- a/test/conformance/ingress/README.md
+++ b/test/conformance/ingress/README.md
@@ -1,4 +1,4 @@
-# Test
+# Ingress Conformance Testing
 
 This directory contains Ingress conformance tests for Knative Ingress resource.
 
@@ -60,6 +60,16 @@ To run the script for all end to end test images:
 $SERVING_ROOT/test/upload-test-images.sh
 ```
 
+## Adding a test
+
+Tests need to be exported and accessible downstream so they should be placed in
+non-test files (ie. sometest.go). Additionally, invoke your test in the default
+`RunConformance` function in [`run.go`](./run.go). This function is the entry
+point by which tests are executed.
+
+This approach aims to reduce the changes required when tests are added &
+removed.
+
 ## Running the tests
 
 ```bash
@@ -75,3 +85,24 @@ go test -v -tags=e2e -count=1 test/conformance/ingress \
     --ingressClass="$INGRESS_CLASS" \
     --ingressendpoint=$INGRESSENDPOINT
 ```
+
+## Running the tests downstream
+
+To run all the conformance tests in your own repo we encourage adopting the
+[`RunConformance`](./run.go) function to run all your tests.
+
+To do so would look something like:
+
+```go
+package conformance
+
+import (
+	"testing"
+	"knative.dev/serving/test/conformance/ingress"
+)
+
+func TestYourIngressConformance(t *testing.T) {
+	ingress.RunConformance(t)
+}
+
+```
diff --git a/third_party/kourier-latest/kourier.yaml b/third_party/kourier-latest/kourier.yaml
index fa1115bc9..a160db6cf 100644
--- a/third_party/kourier-latest/kourier.yaml
+++ b/third_party/kourier-latest/kourier.yaml
@@ -166,7 +166,7 @@ spec:
         app: 3scale-kourier-control
     spec:
       containers:
-      - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:50c4153c679f98e89a4d302c9ed4710d88cb8e342df7c6174beaa442f28b14a4
+      - image: gcr.io/knative-nightly/knative.dev/net-kourier/cmd/kourier@sha256:d19e8a480309208bf47346ef2e25309bc22261d65b42ea7fb399991c579d83fa
         imagePullPolicy: Always
         name: kourier-control
         env:
diff --git a/vendor/knative.dev/pkg/configmap/testing/configmap.go b/vendor/knative.dev/pkg/configmap/testing/configmap.go
index d50dfe610..bd61285bf 100644
--- a/vendor/knative.dev/pkg/configmap/testing/configmap.go
+++ b/vendor/knative.dev/pkg/configmap/testing/configmap.go
@@ -75,7 +75,7 @@ func ConfigMapsFromTestFile(t *testing.T, name string, allowed ...string) (*core
 	}
 	// With the length and membership checks, we know that the keyspace matches.
 
-	exampleBody := orig.Data[configmap.ExampleKey]
+	exampleBody, hasExampleBody := orig.Data[configmap.ExampleKey]
 	// Check that exampleBody does not have lines that end in a trailing space,
 	for i, line := range strings.Split(exampleBody, "\n") {
 		if strings.TrimRightFunc(line, unicode.IsSpace) != line {
@@ -83,6 +83,15 @@ func ConfigMapsFromTestFile(t *testing.T, name string, allowed ...string) (*core
 		}
 	}
 
+	// Check that the hashed exampleBody matches the assigned label, if present.
+	gotChecksum, hasExampleChecksumLabel := orig.Labels[configmap.ExampleChecksumLabel]
+	if hasExampleBody && hasExampleChecksumLabel {
+		wantChecksum := fmt.Sprint(configmap.Checksum(exampleBody))
+		if gotChecksum != wantChecksum {
+			t.Errorf("example checksum label = %s, want %s", gotChecksum, wantChecksum)
+		}
+	}
+
 	// Parse exampleBody into exemplar.Data
 	exemplar := orig.DeepCopy()
 	if err := yaml.Unmarshal([]byte(exampleBody), &exemplar.Data); err != nil {
diff --git a/vendor/knative.dev/pkg/test/gcs/client.go b/vendor/knative.dev/pkg/test/gcs/client.go
new file mode 100644
index 000000000..a78318abe
--- /dev/null
+++ b/vendor/knative.dev/pkg/test/gcs/client.go
@@ -0,0 +1,51 @@
+/*
+Copyright 2020 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package gcs
+
+import (
+	"context"
+
+	"cloud.google.com/go/storage"
+)
+
+type Client interface {
+	// NewStorageBucket creates a new bucket in GCS with uniform access policy
+	NewStorageBucket(ctx context.Context, bkt, project string) error
+	// DeleteStorageBucket removes all children objects, force if not empty
+	DeleteStorageBucket(ctx context.Context, bkt string, force bool) error
+	// Exists check if an object exists under a bucket, assuming bucket exists
+	Exists(ctx context.Context, bkt, objPath string) bool
+	// ListChildrenFiles recursively lists all children files
+	ListChildrenFiles(ctx context.Context, bkt, dirPath string) ([]string, error)
+	// ListDirectChildren lists direct children paths (incl. files and dir)
+	ListDirectChildren(ctx context.Context, bkt, dirPath string) ([]string, error)
+	// AttrObject returns the object attributes
+	AttrObject(ctx context.Context, bkt, objPath string) (*storage.ObjectAttrs, error)
+	// CopyObject copies objects from one location to another, assuming both src and dst
+	// buckets both exist
+	CopyObject(ctx context.Context, srcBkt, srcObjPath, dstBkt, dstObjPath string) error
+	// ReadObject reads a GCS object and returns then contents in []byte
+	ReadObject(ctx context.Context, bkt, objPath string) ([]byte, error)
+	// WriteObject writes []byte content to a GCS object
+	WriteObject(ctx context.Context, bkt, objPath string, content []byte) (int, error)
+	// DeleteObject deletes an object
+	DeleteObject(ctx context.Context, bkt, objPath string) error
+	// Download downloads GCS object to a local file, assuming bucket exists
+	Download(ctx context.Context, bktName, objPath, filePath string) error
+	// Upload uploads a local file to a GCS object, assuming bucket exists
+	Upload(ctx context.Context, bktName, objPath, filePath string) error
+}
diff --git a/vendor/knative.dev/pkg/test/gcs/gcs.go b/vendor/knative.dev/pkg/test/gcs/gcs.go
index 05208c194..fc3cc3e21 100644
--- a/vendor/knative.dev/pkg/test/gcs/gcs.go
+++ b/vendor/knative.dev/pkg/test/gcs/gcs.go
@@ -14,17 +14,14 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-// gcs.go defines functions to use GCS
-
 package gcs
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
-	"log"
-	"net/url"
 	"os"
 	"path"
 	"strings"
@@ -34,54 +31,146 @@ import (
 	"google.golang.org/api/option"
 )
 
-var client *storage.Client
+type GCSClient struct {
+	*storage.Client
+}
 
-// Authenticate explicitly sets up authentication for the rest of run
-func Authenticate(ctx context.Context, serviceAccount string) error {
-	var err error
-	client, err = storage.NewClient(ctx, option.WithCredentialsFile(serviceAccount))
-	return err
+// NewClient creates new GCS client with given service account
+func NewClient(ctx context.Context, serviceAccount string) (*GCSClient, error) {
+	client, err := storage.NewClient(ctx, option.WithCredentialsFile(serviceAccount))
+	if err != nil {
+		return nil, err
+	}
+	return &GCSClient{Client: client}, nil
+}
+
+// NewStorageBucket creates a new bucket in GCS with uniform access policy
+func (g *GCSClient) NewStorageBucket(ctx context.Context, bucketName, project string) error {
+	if project == "" {
+		return errors.New("a project must be provided")
+	}
+
+	if bucketName == "" {
+		return errors.New("a bucket name must be provided")
+	}
+
+	bucket := g.Bucket(bucketName)
+
+	// For now, this creates a bucket with uniform policy across its objects to make ACL
+	// and permission management simple instead of object-level granularity that we currently
+	// do not use anyway.
+	bucketAttr := &storage.BucketAttrs{
+		BucketPolicyOnly: storage.BucketPolicyOnly{
+			Enabled: true,
+		},
+	}
+
+	return bucket.Create(ctx, project, bucketAttr)
+}
+
+// DeleteStorageBucket removes all children objects and then deletes the bucket
+func (g *GCSClient) DeleteStorageBucket(ctx context.Context, bucketName string, force bool) error {
+	children, err := g.ListChildrenFiles(ctx, bucketName, "")
+	if err != nil {
+		return err
+	}
+
+	if len(children) == 0 && !force {
+		return fmt.Errorf("bucket %s not empty, please use force=true", bucketName)
+	}
+
+	for _, child := range children {
+		if err := g.DeleteObject(ctx, bucketName, child); err != nil {
+			return err
+		}
+	}
+	return g.Bucket(bucketName).Delete(ctx)
+}
+
+// get objects iterator under given storagePath and bucketName, use exclusionFilter to eliminate some files.
+func (g *GCSClient) getObjectsIter(ctx context.Context, bucketName, storagePath, exclusionFilter string) *storage.ObjectIterator {
+	return g.Bucket(bucketName).Objects(ctx, &storage.Query{
+		Prefix:    storagePath,
+		Delimiter: exclusionFilter,
+	})
 }
 
-// Exists checks if path exist under gcs bucket,
-// this path can either be a directory or a file.
-func Exists(ctx context.Context, bucketName, storagePath string) bool {
+// Exists check if an object exists under a bucket, assuming bucket exists
+func (g *GCSClient) Exists(ctx context.Context, bucketName, objPath string) bool {
 	// Check if this is a file
-	handle := createStorageObject(bucketName, storagePath)
-	if _, err := handle.Attrs(ctx); err == nil {
+	objHandle := g.Bucket(bucketName).Object(objPath)
+	if _, err := objHandle.Attrs(ctx); err == nil {
 		return true
 	}
+
 	// Check if this is a directory,
-	// gcs directory paths are virtual paths, they automatically got deleted if there is no child file
-	_, err := getObjectsIter(ctx, bucketName, strings.TrimRight(storagePath, " /")+"/", "").Next()
+	// gcs directory paths are virtual paths, they automatically get deleted if there is no child file
+	_, err := g.getObjectsIter(ctx, bucketName, strings.TrimRight(objPath, " /")+"/", "").Next()
 	return err == nil
 }
 
+// list child under storagePath, use exclusionFilter for skipping some files.
+// This function gets all child files recursively under given storagePath,
+// then filter out filenames containing given exclusionFilter.
+// If exclusionFilter is empty string, returns all files but not directories,
+// if exclusionFilter is "/", returns all direct children, including both files and directories.
+// see https://godoc.org/cloud.google.com/go/storage#Query
+func (g *GCSClient) list(ctx context.Context, bucketName, storagePath, exclusionFilter string) ([]string, error) {
+	objsAttrs, err := g.getObjectsAttrs(ctx, bucketName, storagePath, exclusionFilter)
+	if err != nil {
+		return nil, err
+	}
+	var filePaths []string
+	for _, attrs := range objsAttrs {
+		filePaths = append(filePaths, path.Join(attrs.Prefix, attrs.Name))
+	}
+	return filePaths, nil
+}
+
+// Query items under given gcs storagePath, use exclusionFilter to eliminate some files.
+func (g *GCSClient) getObjectsAttrs(ctx context.Context, bucketName, storagePath,
+	exclusionFilter string) ([]*storage.ObjectAttrs, error) {
+	var allAttrs []*storage.ObjectAttrs
+	it := g.getObjectsIter(ctx, bucketName, storagePath, exclusionFilter)
+
+	for {
+		attrs, err := it.Next()
+		if err == iterator.Done {
+			break
+		}
+		if err != nil {
+			return nil, fmt.Errorf("error iterating: %v", err)
+		}
+		allAttrs = append(allAttrs, attrs)
+	}
+	return allAttrs, nil
+}
+
 // ListChildrenFiles recursively lists all children files.
-func ListChildrenFiles(ctx context.Context, bucketName, storagePath string) []string {
-	return list(ctx, bucketName, strings.TrimRight(storagePath, " /")+"/", "")
+func (g *GCSClient) ListChildrenFiles(ctx context.Context, bucketName, dirPath string) ([]string, error) {
+	return g.list(ctx, bucketName, strings.TrimRight(dirPath, " /")+"/", "")
 }
 
 // ListDirectChildren lists direct children paths (including files and directories).
-func ListDirectChildren(ctx context.Context, bucketName, storagePath string) []string {
+func (g *GCSClient) ListDirectChildren(ctx context.Context, bucketName, dirPath string) ([]string, error) {
 	// If there are 2 directories named "foo" and "foobar",
 	// then given storagePath "foo" will get files both under "foo" and "foobar".
 	// Add trailling slash to storagePath, so that only gets children under given directory.
-	return list(ctx, bucketName, strings.TrimRight(storagePath, " /")+"/", "/")
+	return g.list(ctx, bucketName, strings.TrimRight(dirPath, " /")+"/", "/")
 }
 
-// Copy file from within gcs
-func Copy(ctx context.Context, srcBucketName, srcPath, dstBucketName, dstPath string) error {
-	src := createStorageObject(srcBucketName, srcPath)
-	dst := createStorageObject(dstBucketName, dstPath)
+// CopyObject copies objects from one location to another. Assumes both source and destination buckets exist.
+func (g *GCSClient) CopyObject(ctx context.Context, srcBucketName, srcPath, dstBucketName, dstPath string) error {
+	src := g.Bucket(srcBucketName).Object(srcPath)
+	dst := g.Bucket(dstBucketName).Object(dstPath)
 
 	_, err := dst.CopierFrom(src).Run(ctx)
 	return err
 }
 
-// Download file from gcs
-func Download(ctx context.Context, bucketName, srcPath, dstPath string) error {
-	handle := createStorageObject(bucketName, srcPath)
+// Download gcs object to a file
+func (g *GCSClient) Download(ctx context.Context, bucketName, objPath, dstPath string) error {
+	handle := g.Bucket(bucketName).Object(objPath)
 	if _, err := handle.Attrs(ctx); err != nil {
 		return err
 	}
@@ -99,22 +188,28 @@ func Download(ctx context.Context, bucketName, srcPath, dstPath string) error {
 	return err
 }
 
-// Upload file to gcs
-func Upload(ctx context.Context, bucketName, dstPath, srcPath string) error {
+// Upload file to gcs object
+func (g *GCSClient) Upload(ctx context.Context, bucketName, objPath, srcPath string) error {
 	src, err := os.Open(srcPath)
 	if err != nil {
 		return err
 	}
-	dst := createStorageObject(bucketName, dstPath).NewWriter(ctx)
+	dst := g.Bucket(bucketName).Object(objPath).NewWriter(ctx)
 	defer dst.Close()
 	_, err = io.Copy(dst, src)
 	return err
 }
 
-// Read reads the specified file
-func Read(ctx context.Context, bucketName, filePath string) ([]byte, error) {
+// AttrObject returns the object attributes
+func (g *GCSClient) AttrObject(ctx context.Context, bucketName, objPath string) (*storage.ObjectAttrs, error) {
+	objHandle := g.Bucket(bucketName).Object(objPath)
+	return objHandle.Attrs(ctx)
+}
+
+// ReadObject reads the content of a gcs object
+func (g *GCSClient) ReadObject(ctx context.Context, bucketName, objPath string) ([]byte, error) {
 	var contents []byte
-	f, err := NewReader(ctx, bucketName, filePath)
+	f, err := g.NewReader(ctx, bucketName, objPath)
 	if err != nil {
 		return contents, err
 	}
@@ -122,103 +217,43 @@ func Read(ctx context.Context, bucketName, filePath string) ([]byte, error) {
 	return ioutil.ReadAll(f)
 }
 
-// ReadURL reads from a gsUrl and return a log structure
-func ReadURL(ctx context.Context, gcsURL string) ([]byte, error) {
-	bucket, obj, err := linkToBucketAndObject(gcsURL)
-	if err != nil {
-		return nil, err
-	}
-
-	return Read(ctx, bucket, obj)
-}
-
 // NewReader creates a new Reader of a gcs file.
 // Important: caller must call Close on the returned Reader when done reading
-func NewReader(ctx context.Context, bucketName, filePath string) (*storage.Reader, error) {
-	o := createStorageObject(bucketName, filePath)
+func (g *GCSClient) NewReader(ctx context.Context, bucketName, objPath string) (*storage.Reader, error) {
+	o := g.Bucket(bucketName).Object(objPath)
 	if _, err := o.Attrs(ctx); err != nil {
 		return nil, err
 	}
 	return o.NewReader(ctx)
 }
 
-// BuildLogPath returns the build log path from the test result gcsURL
-func BuildLogPath(gcsURL string) (string, error) {
-	u, err := url.Parse(gcsURL)
-	if err != nil {
-		return gcsURL, err
-	}
-	u.Path = path.Join(u.Path, "build-log.txt")
-	return u.String(), nil
-}
-
-// GetConsoleURL returns the gcs link renderable directly from a browser
-func GetConsoleURL(gcsURL string) (string, error) {
-	u, err := url.Parse(gcsURL)
-	if err != nil {
-		return gcsURL, err
-	}
-	u.Path = path.Join("storage/browser", u.Host, u.Path)
-	u.Scheme = "https"
-	u.Host = "console.cloud.google.com"
-	return u.String(), nil
+// DeleteObject deletes an object
+func (g *GCSClient) DeleteObject(ctx context.Context, bucketName, objPath string) error {
+	objHandle := g.Bucket(bucketName).Object(objPath)
+	return objHandle.Delete(ctx)
 }
 
-// create storage object handle, this step doesn't access internet
-func createStorageObject(bucketName, filePath string) *storage.ObjectHandle {
-	return client.Bucket(bucketName).Object(filePath)
-}
-
-// Query items under given gcs storagePath, use exclusionFilter to eliminate some files.
-func getObjectsAttrs(ctx context.Context, bucketName, storagePath, exclusionFilter string) []*storage.ObjectAttrs {
-	var allAttrs []*storage.ObjectAttrs
-	it := getObjectsIter(ctx, bucketName, storagePath, exclusionFilter)
-
-	for {
-		attrs, err := it.Next()
-		if err == iterator.Done {
-			break
+// WriteObject writes the content to a gcs object
+func (g *GCSClient) WriteObject(ctx context.Context, bucketName, objPath string,
+	content []byte) (n int, err error) {
+	objWriter := g.Bucket(bucketName).Object(objPath).NewWriter(ctx)
+	defer func() {
+		cerr := objWriter.Close()
+		if err == nil {
+			err = cerr
 		}
-		if err != nil {
-			log.Fatalf("Error iterating: %v", err)
-		}
-		allAttrs = append(allAttrs, attrs)
-	}
-	return allAttrs
-}
+	}()
 
-// list child under storagePath, use exclusionFilter for skipping some files.
-// This function gets all child files recursively under given storagePath,
-// then filter out filenames containing giving exclusionFilter.
-// If exclusionFilter is empty string, returns all files but not directories,
-// if exclusionFilter is "/", returns all direct children, including both files and directories.
-// see https://godoc.org/cloud.google.com/go/storage#Query
-func list(ctx context.Context, bucketName, storagePath, exclusionFilter string) []string {
-	objsAttrs := getObjectsAttrs(ctx, bucketName, storagePath, exclusionFilter)
-	filePaths := make([]string, 0, len(objsAttrs))
-	for _, attrs := range objsAttrs {
-		filePaths = append(filePaths, path.Join(attrs.Prefix, attrs.Name))
-	}
-	return filePaths
+	n, err = objWriter.Write(content)
+	return
 }
 
-// get objects iterator under given storagePath and bucketName, use exclusionFilter to eliminate some files.
-func getObjectsIter(ctx context.Context, bucketName, storagePath, exclusionFilter string) *storage.ObjectIterator {
-	return client.Bucket(bucketName).Objects(ctx, &storage.Query{
-		Prefix:    storagePath,
-		Delimiter: exclusionFilter,
-	})
-}
-
-// get the bucket and object from the gsURL
-func linkToBucketAndObject(gsURL string) (string, string, error) {
-	var bucket, obj string
-	gsURL = strings.Replace(gsURL, "gs://", "", 1)
-
-	sIdx := strings.IndexByte(gsURL, '/')
-	if sIdx == -1 || sIdx+1 >= len(gsURL) {
-		return bucket, obj, fmt.Errorf("the gsUrl (%s) cannot be converted to bucket/object", gsURL)
+// ReadURL reads from a gsUrl and return a log structure
+func (g *GCSClient) ReadURL(ctx context.Context, gcsURL string) ([]byte, error) {
+	bucket, obj, err := linkToBucketAndObject(gcsURL)
+	if err != nil {
+		return nil, err
 	}
 
-	return gsURL[:sIdx], gsURL[sIdx+1:], nil
+	return g.ReadObject(ctx, bucket, obj)
 }
diff --git a/vendor/knative.dev/pkg/test/gcs/helpers.go b/vendor/knative.dev/pkg/test/gcs/helpers.go
new file mode 100644
index 000000000..150999ed8
--- /dev/null
+++ b/vendor/knative.dev/pkg/test/gcs/helpers.go
@@ -0,0 +1,58 @@
+/*
+Copyright 2020 The Knative Authors
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package gcs
+
+import (
+	"fmt"
+	"net/url"
+	"path"
+	"strings"
+)
+
+// get the bucket and object from the gsURL
+func linkToBucketAndObject(gsURL string) (string, string, error) {
+	gsURL = strings.Replace(gsURL, "gs://", "", 1)
+
+	sIdx := strings.IndexByte(gsURL, '/')
+	if sIdx == -1 || sIdx+1 >= len(gsURL) {
+		return "", "", fmt.Errorf("the gsUrl (%q) cannot be converted to bucket/object", gsURL)
+	}
+
+	return gsURL[:sIdx], gsURL[sIdx+1:], nil
+}
+
+// BuildLogPath returns the build log path from the test result gcsURL
+func BuildLogPath(gcsURL string) (string, error) {
+	u, err := url.Parse(gcsURL)
+	if err != nil {
+		return gcsURL, err
+	}
+	u.Path = path.Join(u.Path, "build-log.txt")
+	return u.String(), nil
+}
+
+// GetConsoleURL returns the gcs link renderable directly from a browser
+func GetConsoleURL(gcsURL string) (string, error) {
+	u, err := url.Parse(gcsURL)
+	if err != nil {
+		return gcsURL, err
+	}
+	u.Path = path.Join("storage/browser", u.Host, u.Path)
+	u.Scheme = "https"
+	u.Host = "console.cloud.google.com"
+	return u.String(), nil
+}
diff --git a/vendor/knative.dev/pkg/test/junit/junit.go b/vendor/knative.dev/pkg/test/junit/junit.go
index 2e53da618..bc69067be 100644
--- a/vendor/knative.dev/pkg/test/junit/junit.go
+++ b/vendor/knative.dev/pkg/test/junit/junit.go
@@ -21,6 +21,8 @@ package junit
 import (
 	"encoding/xml"
 	"fmt"
+	"io/ioutil"
+	"log"
 )
 
 // TestStatusEnum is a enum for test result status
@@ -144,3 +146,24 @@ func UnMarshal(buf []byte) (*TestSuites, error) {
 	}
 	return &testSuites, nil
 }
+
+// CreateXMLErrorMsg outputs a junit testsuite, testname and error message to the destination path
+// in XML format
+func CreateXMLErrorMsg(testSuite, testName, errMsg, dest string) {
+	suites := TestSuites{}
+	suite := TestSuite{Name: testSuite}
+	var errP *string
+	if errMsg != "" {
+		errP = &errMsg
+	}
+	suite.AddTestCase(TestCase{
+		Name:    testName,
+		Failure: errP,
+	})
+	suites.AddTestSuite(&suite)
+	contents, err := suites.ToBytes("", "")
+	if err != nil {
+		log.Fatal(err)
+	}
+	ioutil.WriteFile(dest, contents, 0644)
+}
diff --git a/vendor/knative.dev/pkg/test/prow/prow.go b/vendor/knative.dev/pkg/test/prow/prow.go
index 2af8a0095..c5304ce27 100644
--- a/vendor/knative.dev/pkg/test/prow/prow.go
+++ b/vendor/knative.dev/pkg/test/prow/prow.go
@@ -59,8 +59,8 @@ const (
 
 // defined here so that it can be mocked for unit testing
 var logFatalf = log.Fatalf
-
 var ctx = context.Background()
+var client *gcs.GCSClient
 
 // Job struct represents a job directory in gcs.
 // gcs job StoragePath will be derived from Type if it's defined,
@@ -128,7 +128,9 @@ func GetLocalArtifactsDir() string {
 
 // Initialize wraps gcs authentication, have to be invoked before any other functions
 func Initialize(serviceAccount string) error {
-	return gcs.Authenticate(ctx, serviceAccount)
+	var err error
+	client, err = gcs.NewClient(ctx, serviceAccount)
+	return err
 }
 
 // NewJob creates new job struct
@@ -158,13 +160,13 @@ func NewJob(jobName, jobType, orgName, repoName string, pullID int) *Job {
 
 // PathExists checks if the storage path of a job exists in gcs or not
 func (j *Job) PathExists() bool {
-	return gcs.Exists(ctx, BucketName, j.StoragePath)
+	return client.Exists(ctx, BucketName, j.StoragePath)
 }
 
 // GetLatestBuildNumber gets the latest build number for job
 func (j *Job) GetLatestBuildNumber() (int, error) {
 	logFilePath := path.Join(j.StoragePath, Latest)
-	contents, err := gcs.Read(ctx, BucketName, logFilePath)
+	contents, err := client.ReadObject(ctx, BucketName, logFilePath)
 	if err != nil {
 		return 0, err
 	}
@@ -223,7 +225,7 @@ func (j *Job) GetBuilds() []Build {
 // for job, keeps the ones that can be parsed as integer
 func (j *Job) GetBuildIDs() []int {
 	var buildIDs []int
-	gcsBuildPaths := gcs.ListDirectChildren(ctx, j.Bucket, j.StoragePath)
+	gcsBuildPaths, _ := client.ListDirectChildren(ctx, j.Bucket, j.StoragePath)
 	for _, gcsBuildPath := range gcsBuildPaths {
 		if buildID, err := getBuildIDFromBuildPath(gcsBuildPath); err == nil {
 			buildIDs = append(buildIDs, buildID)
@@ -256,12 +258,12 @@ func (j *Job) GetLatestBuilds(count int) []Build {
 
 // IsStarted check if build has started by looking at "started.json" file
 func (b *Build) IsStarted() bool {
-	return gcs.Exists(ctx, BucketName, path.Join(b.StoragePath, StartedJSON))
+	return client.Exists(ctx, BucketName, path.Join(b.StoragePath, StartedJSON))
 }
 
 // IsFinished check if build has finished by looking at "finished.json" file
 func (b *Build) IsFinished() bool {
-	return gcs.Exists(ctx, BucketName, path.Join(b.StoragePath, FinishedJSON))
+	return client.Exists(ctx, BucketName, path.Join(b.StoragePath, FinishedJSON))
 }
 
 // GetStartTime gets started timestamp of a build,
@@ -286,7 +288,8 @@ func (b *Build) GetFinishTime() (int64, error) {
 
 // GetArtifacts gets gcs path for all artifacts of current build
 func (b *Build) GetArtifacts() []string {
-	return gcs.ListChildrenFiles(ctx, BucketName, b.GetArtifactsDir())
+	artifacts, _ := client.ListChildrenFiles(ctx, BucketName, b.GetArtifactsDir())
+	return artifacts
 }
 
 // GetArtifactsDir gets gcs path for artifacts of current build
@@ -302,7 +305,7 @@ func (b *Build) GetBuildLogPath() string {
 // ReadFile reads given file of current build,
 // relPath is the file path relative to build directory
 func (b *Build) ReadFile(relPath string) ([]byte, error) {
-	return gcs.Read(ctx, BucketName, path.Join(b.StoragePath, relPath))
+	return client.ReadObject(ctx, BucketName, path.Join(b.StoragePath, relPath))
 }
 
 // ParseLog parses the build log and returns the lines where the checkLog func does not return an empty slice,
@@ -310,7 +313,7 @@ func (b *Build) ReadFile(relPath string) ([]byte, error) {
 func (b *Build) ParseLog(checkLog func(s []string) *string) ([]string, error) {
 	var logs []string
 
-	f, err := gcs.NewReader(ctx, b.Bucket, b.GetBuildLogPath())
+	f, err := client.NewReader(ctx, b.Bucket, b.GetBuildLogPath())
 	if err != nil {
 		return logs, err
 	}
@@ -333,7 +336,7 @@ func getBuildIDFromBuildPath(buildPath string) (int, error) {
 // unmarshalJSONFile reads a file from gcs, parses it with xml and write to v.
 // v must be an arbitrary struct, slice, or string.
 func unmarshalJSONFile(storagePath string, v interface{}) error {
-	contents, err := gcs.Read(ctx, BucketName, storagePath)
+	contents, err := client.ReadObject(ctx, BucketName, storagePath)
 	if err != nil {
 		return err
 	}