Repository: kserve/kserve

Issue:
Upgrading KFServing to KNative 0.11
/kind feature

**Describe the solution you'd like**
KFServing needs to be upgraded to KNative 0.10 for getting the latest enhancements around cold starts, caching etc.

This requires a chain of cascading dependencies.

KNative 0.10 takes a dependency on Kube 1.15.3 APIs . Best is to revisit this from backwards now, first migrating KFServing dependencies to Kube 1.14+ APIs et all before visiting KNative 0.10. We can follow a more sequential approach

1. openapi code gen for 1.14 and 1.15 has migrated to another pkg (k8s.io/kube-openapi/cmd/openapi-gen) which causes some compatibility issues with k8s 1.15.3. 
@pugangxa @jinchihe 

2. We also need to update the code gen config since the new code gen now is doing some API naming check by default (e.g. the API rule violation).  Unit tests may also need to be migrated to the new rules. Code gen files that need additional flags:
https://github.com/kubeflow/kfserving/blob/master/hack/update-codegen.sh
https://github.com/kubeflow/kfserving/blob/master/hack/update-openapigen.sh

API names match rule: 
https://github.com/kubernetes/kube-openapi/blob/master/pkg/generators/rules/names_match.go#L54-L76

e.g. According to the new name matching, StorageURI in json should be storageURI (not storageUri), so we may want to ignore some rule checking or update all our current API naming and bump it to a new api version.

 @pugangxa @jinchihe 

3. controller-runtime and controller-tools need to migrate to a version where the admission webhook type pkg is deprecated. We need to figure out which pkg we should migrate to the new version and use the new webhook implementation.
@hougangliu 

4. There are also few type changes that get introduced in 1.14 and 1.15 that we need to fix. Unfortunately I can’t get to this part yet so I can’t estimate how much effort it will need. k8s.io vendor libraries need to be migrated to Kube 1.15.3
@hougangliu 

5. Knative APIs need to be migrated to V1 from V1alpha1
@Tomcli 

6. KNative libraries need to be upgraded to 0.10
@animeshsingh 


Discussion:
/assign @hougangliu @jinchihe @pugangxa @Tomcli @animeshsingh 
@animeshsingh: Reopened this issue.

<details>

In response to [this](https://github.com/kubeflow/kfserving/issues/596#issuecomment-566674556):

>/reopen


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>

Resolving patch:
diff --git a/python/kfserving/kfserving/api/kf_serving_watch.py b/python/kfserving/kfserving/api/kf_serving_watch.py
--- a/python/kfserving/kfserving/api/kf_serving_watch.py
+++ b/python/kfserving/kfserving/api/kf_serving_watch.py
@@ -40,16 +40,16 @@ def watch(name=None, namespace=None, timeout_seconds=600):
         timeout_seconds=timeout_seconds)
 
     for event in stream:
-        kfserivce = event['object']
-        isvc_name = kfserivce['metadata']['name']
+        isvc = event['object']
+        isvc_name = isvc['metadata']['name']
         if name and name != isvc_name:
             continue
         else:
-            url = kfserivce['status'].get('url', '')
-            default_traffic = kfserivce['status'].get('traffic', '')
-            canary_traffic = kfserivce['status'].get('canaryTraffic', '')
+            url = isvc['status'].get('url', '')
+            default_traffic = isvc['status'].get('traffic', '')
+            canary_traffic = isvc['status'].get('canaryTraffic', '')
             status = 'Unknown'
-            for condition in kfserivce['status'].get('conditions', {}):
+            for condition in isvc['status'].get('conditions', {}):
                 if condition.get('type', '') == 'Ready':
                     status = condition.get('status', 'Unknown')
             tbl(isvc_name, status, default_traffic, canary_traffic, url)


Test patch:
diff --git a/pkg/apis/serving/v1alpha2/inferenceservice_types_test.go b/pkg/apis/serving/v1alpha2/inferenceservice_types_test.go
--- a/pkg/apis/serving/v1alpha2/inferenceservice_types_test.go
+++ b/pkg/apis/serving/v1alpha2/inferenceservice_types_test.go
@@ -88,21 +88,21 @@ func TestInferenceService(t *testing.T) {
 		Traffic:       20,
 		CanaryTraffic: 80,
 		Default: &ComponentStatusMap{
-			constants.Predictor: &StatusConfigurationSpec{
+			constants.Predictor: StatusConfigurationSpec{
 				Name:     "v1",
 				Replicas: 2,
 			},
 		},
 		Canary: &ComponentStatusMap{
-			constants.Predictor: &StatusConfigurationSpec{
+			constants.Predictor: StatusConfigurationSpec{
 				Name:     "v2",
 				Replicas: 3,
 			},
 		},
 	}
-	g.Expect(c.Update(context.TODO(), statusUpdated)).NotTo(gomega.HaveOccurred())
+	g.Expect(c.Status().Update(context.TODO(), statusUpdated)).NotTo(gomega.HaveOccurred())
 	g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
-	g.Expect(fetched).To(gomega.Equal(statusUpdated))
+	g.Expect(fetched.Status).To(gomega.Equal(statusUpdated.Status))
 
 	// Test Delete
 	g.Expect(c.Delete(context.TODO(), fetched)).NotTo(gomega.HaveOccurred())
diff --git a/pkg/apis/serving/v1alpha2/v1alpha2_suite_test.go b/pkg/apis/serving/v1alpha2/v1alpha2_suite_test.go
--- a/pkg/apis/serving/v1alpha2/v1alpha2_suite_test.go
+++ b/pkg/apis/serving/v1alpha2/v1alpha2_suite_test.go
@@ -48,7 +48,7 @@ const (
 
 func TestMain(m *testing.M) {
 	t := &envtest.Environment{
-		CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "config", "default", "crds")},
+		CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "..", "config", "default", "crds", "base")},
 	}
 
 	err := SchemeBuilder.AddToScheme(scheme.Scheme)
diff --git a/pkg/controller/inferenceservice/controller_test.go b/pkg/controller/inferenceservice/controller_test.go
--- a/pkg/controller/inferenceservice/controller_test.go
+++ b/pkg/controller/inferenceservice/controller_test.go
@@ -18,6 +18,7 @@ package service
 
 import (
 	"fmt"
+	"github.com/kubeflow/kfserving/pkg/controller/inferenceservice/resources/istio"
 	"knative.dev/pkg/network"
 	"testing"
 	"time"
@@ -38,14 +39,12 @@ import (
 	kfserving "github.com/kubeflow/kfserving/pkg/apis/serving/v1alpha2"
 	"github.com/onsi/gomega"
 	"golang.org/x/net/context"
+	istiov1alpha3 "istio.io/api/networking/v1alpha3"
+	"istio.io/client-go/pkg/apis/networking/v1alpha3"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	duckv1 "knative.dev/pkg/apis/duck/v1"
 	duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
-	"knative.dev/pkg/apis/istio/common/v1alpha1"
-	istiov1alpha1 "knative.dev/pkg/apis/istio/common/v1alpha1"
-	"knative.dev/pkg/apis/istio/v1alpha3"
-	istiov1alpha3 "knative.dev/pkg/apis/istio/v1alpha3"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/manager"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -118,7 +117,7 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 	g := gomega.NewGomegaWithT(t)
 	// Setup the Manager and Controller.  Wrap the Controller Reconcile function so it writes each request to a
 	// channel when it is finished.
-	mgr, err := manager.New(cfg, manager.Options{})
+	mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"})
 	g.Expect(err).NotTo(gomega.HaveOccurred())
 	c = mgr.GetClient()
 
@@ -213,12 +212,12 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 	g.Expect(c.Status().Update(context.TODO(), updateDefault)).NotTo(gomega.HaveOccurred())
 	g.Eventually(requests, timeout).Should(gomega.Receive(gomega.Equal(expectedRequest)))
 
-	virtualService := &istiov1alpha3.VirtualService{}
+	virtualService := &v1alpha3.VirtualService{}
 	g.Eventually(func() error { return c.Get(context.TODO(), virtualServiceName, virtualService) }, timeout).
 		Should(gomega.Succeed())
 
-	expectedVirtualService := &istiov1alpha3.VirtualService{
-		Spec: istiov1alpha3.VirtualServiceSpec{
+	expectedVirtualService := &v1alpha3.VirtualService{
+		Spec: istiov1alpha3.VirtualService{
 			Gateways: []string{
 				constants.KnativeIngressGateway,
 				constants.KnativeLocalGateway,
@@ -227,38 +226,46 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 				constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain),
 				network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace),
 			},
-			HTTP: []istiov1alpha3.HTTPRoute{
+			Http: []*istiov1alpha3.HTTPRoute{
 				{
-					Match: []istiov1alpha3.HTTPMatchRequest{
+					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeIngressGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+								},
 							},
 						},
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeLocalGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+								},
 							},
 						},
 					},
-					Route: []istiov1alpha3.HTTPRouteDestination{
+					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: network.GetServiceHostname("cluster-local-gateway", "istio-system"),
 							},
 							Weight: 100,
@@ -266,7 +273,7 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
 						Attempts:      3,
-						PerTryTimeout: "10m",
+						PerTryTimeout: istio.RetryTimeout,
 					},
 				},
 			},
@@ -303,7 +310,7 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 		Traffic:       100,
 		CanaryTraffic: 0,
 		Default: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
@@ -366,7 +373,7 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 				},
 			},
 			Default: &kfserving.ComponentStatusMap{
-				constants.Predictor: &kfserving.StatusConfigurationSpec{
+				constants.Predictor: kfserving.StatusConfigurationSpec{
 					Name: "revision-v1",
 				},
 			},
@@ -526,14 +533,14 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 		Traffic:       80,
 		CanaryTraffic: 20,
 		Default: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name: "revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(canaryServiceKey.Name), canaryServiceKey.Namespace,
 					domain),
 			},
 		},
 		Canary: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name: "revision-v2",
 				Hostname: constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(canaryServiceKey.Name), canaryServiceKey.Namespace,
 					domain),
@@ -548,12 +555,12 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 		return cmp.Diff(&expectedKfsvcStatus, &isvc.Status, cmpopts.IgnoreTypes(apis.VolatileTime{}))
 	}, timeout).Should(gomega.BeEmpty())
 
-	virtualService := &istiov1alpha3.VirtualService{}
+	virtualService := &v1alpha3.VirtualService{}
 	g.Eventually(func() error { return c.Get(context.TODO(), virtualServiceName, virtualService) }, timeout).
 		Should(gomega.Succeed())
 
-	expectedVirtualService := &istiov1alpha3.VirtualService{
-		Spec: istiov1alpha3.VirtualServiceSpec{
+	expectedVirtualService := &v1alpha3.VirtualService{
+		Spec: istiov1alpha3.VirtualService{
 			Gateways: []string{
 				constants.KnativeIngressGateway,
 				constants.KnativeLocalGateway,
@@ -562,51 +569,59 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 				constants.InferenceServiceHostName(canaryServiceKey.Name, canaryServiceKey.Namespace, domain),
 				network.GetServiceHostname(canaryServiceKey.Name, canaryServiceKey.Namespace),
 			},
-			HTTP: []istiov1alpha3.HTTPRoute{
+			Http: []*istiov1alpha3.HTTPRoute{
 				{
-					Match: []istiov1alpha3.HTTPMatchRequest{
+					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(canaryServiceKey.Name),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(canaryServiceKey.Name),
+								},
 							},
 							Gateways: []string{constants.KnativeIngressGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(constants.InferenceServiceHostName(canaryServiceKey.Name, canaryServiceKey.Namespace, domain)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(constants.InferenceServiceHostName(canaryServiceKey.Name, canaryServiceKey.Namespace, domain)),
+								},
 							},
 						},
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(canaryServiceKey.Name),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(canaryServiceKey.Name),
+								},
 							},
 							Gateways: []string{constants.KnativeLocalGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(network.GetServiceHostname(canaryServiceKey.Name, canaryServiceKey.Namespace)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(network.GetServiceHostname(canaryServiceKey.Name, canaryServiceKey.Namespace)),
+								},
 							},
 						},
 					},
-					Route: []istiov1alpha3.HTTPRouteDestination{
+					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(canaryServiceKey.Name), canaryServiceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: constants.LocalGatewayHost,
 							},
 							Weight: 80,
 						},
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.CanaryPredictorServiceName(canaryServiceKey.Name), canaryServiceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: constants.LocalGatewayHost,
 							},
 							Weight: 20,
@@ -614,7 +629,7 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
 						Attempts:      3,
-						PerTryTimeout: "10m",
+						PerTryTimeout: istio.RetryTimeout,
 					},
 				},
 			},
@@ -669,7 +684,7 @@ func TestCanaryDelete(t *testing.T) {
 		Status: kfserving.InferenceServiceStatus{
 			URL: canaryServiceKey.Name + ".svc.cluster.local",
 			Default: &kfserving.ComponentStatusMap{
-				constants.Predictor: &kfserving.StatusConfigurationSpec{
+				constants.Predictor: kfserving.StatusConfigurationSpec{
 					Name: "revision-v1",
 				},
 			},
@@ -781,13 +796,13 @@ func TestCanaryDelete(t *testing.T) {
 		Traffic:       80,
 		CanaryTraffic: 20,
 		Default: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceName), namespace, domain),
 			},
 		},
 		Canary: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v2",
 				Hostname: constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(serviceName), namespace, domain),
 			},
@@ -803,11 +818,11 @@ func TestCanaryDelete(t *testing.T) {
 	}, timeout).Should(gomega.BeEmpty())
 
 	// should see a virtual service with 2 routes
-	virtualService := &istiov1alpha3.VirtualService{}
+	virtualService := &v1alpha3.VirtualService{}
 	g.Eventually(func() error { return c.Get(context.TODO(), virtualServiceName, virtualService) }, timeout).
 		Should(gomega.Succeed())
-	g.Expect(len(virtualService.Spec.HTTP)).To(gomega.Equal(1))
-	g.Expect(len(virtualService.Spec.HTTP[0].Route)).To(gomega.Equal(2))
+	g.Expect(len(virtualService.Spec.Http)).To(gomega.Equal(1))
+	g.Expect(len(virtualService.Spec.Http[0].Route)).To(gomega.Equal(2))
 
 	// Update instance to remove Canary Spec
 	// Canary service should be removed during reconcile
@@ -866,7 +881,7 @@ func TestCanaryDelete(t *testing.T) {
 		},
 		Traffic: 100,
 		Default: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceName), namespace, domain),
 			},
@@ -883,11 +898,11 @@ func TestCanaryDelete(t *testing.T) {
 	}, timeout).Should(testutils.BeSematicEqual(&expectedKfsvcStatus))
 
 	// should see a virtual service with only 1 route
-	virtualService = &istiov1alpha3.VirtualService{}
+	virtualService = &v1alpha3.VirtualService{}
 	g.Eventually(func() error { return c.Get(context.TODO(), virtualServiceName, virtualService) }, timeout).
 		Should(gomega.Succeed())
-	g.Expect(len(virtualService.Spec.HTTP)).To(gomega.Equal(1))
-	g.Expect(len(virtualService.Spec.HTTP[0].Route)).To(gomega.Equal(1))
+	g.Expect(len(virtualService.Spec.Http)).To(gomega.Equal(1))
+	g.Expect(len(virtualService.Spec.Http[0].Route)).To(gomega.Equal(1))
 
 }
 
@@ -963,7 +978,7 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 		Status: kfserving.InferenceServiceStatus{
 			URL: serviceName + ".svc.cluster.local",
 			Default: &kfserving.ComponentStatusMap{
-				constants.Predictor: &kfserving.StatusConfigurationSpec{
+				constants.Predictor: kfserving.StatusConfigurationSpec{
 					Name: "revision-v1",
 				},
 			},
@@ -1168,21 +1183,21 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 			},
 		},
 		Default: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
-			constants.Transformer: &kfserving.StatusConfigurationSpec{
+			constants.Transformer: kfserving.StatusConfigurationSpec{
 				Name:     "t-revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultTransformerServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
 		},
 		Canary: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v2",
 				Hostname: constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
-			constants.Transformer: &kfserving.StatusConfigurationSpec{
+			constants.Transformer: kfserving.StatusConfigurationSpec{
 				Name:     "t-revision-v2",
 				Hostname: constants.InferenceServiceHostName(constants.CanaryTransformerServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
@@ -1197,12 +1212,12 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 	}, timeout).Should(gomega.BeEmpty())
 
 	// verify virtual service points to transformer
-	virtualService := &istiov1alpha3.VirtualService{}
+	virtualService := &v1alpha3.VirtualService{}
 	g.Eventually(func() error { return c.Get(context.TODO(), virtualServiceName, virtualService) }, timeout).
 		Should(gomega.Succeed())
 
-	expectedVirtualService := &istiov1alpha3.VirtualService{
-		Spec: istiov1alpha3.VirtualServiceSpec{
+	expectedVirtualService := &v1alpha3.VirtualService{
+		Spec: istiov1alpha3.VirtualService{
 			Gateways: []string{
 				constants.KnativeIngressGateway,
 				constants.KnativeLocalGateway,
@@ -1211,51 +1226,59 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 				constants.InferenceServiceHostName(serviceName, serviceKey.Namespace, domain),
 				network.GetServiceHostname(serviceName, serviceKey.Namespace),
 			},
-			HTTP: []istiov1alpha3.HTTPRoute{
+			Http: []*istiov1alpha3.HTTPRoute{
 				{
-					Match: []istiov1alpha3.HTTPMatchRequest{
+					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeIngressGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+								},
 							},
 						},
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeLocalGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+								},
 							},
 						},
 					},
-					Route: []istiov1alpha3.HTTPRouteDestination{
+					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultTransformerServiceName(serviceName), serviceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: constants.LocalGatewayHost,
 							},
 							Weight: 80,
 						},
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.CanaryTransformerServiceName(serviceName), serviceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: constants.LocalGatewayHost,
 							},
 							Weight: 20,
@@ -1263,7 +1286,7 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
 						Attempts:      3,
-						PerTryTimeout: "10m",
+						PerTryTimeout: istio.RetryTimeout,
 					},
 				},
 			},
@@ -1343,7 +1366,7 @@ func TestInferenceServiceDeleteComponent(t *testing.T) {
 		Status: kfserving.InferenceServiceStatus{
 			URL: serviceName + ".svc.cluster.local",
 			Default: &kfserving.ComponentStatusMap{
-				constants.Predictor: &kfserving.StatusConfigurationSpec{
+				constants.Predictor: kfserving.StatusConfigurationSpec{
 					Name: "revision-v1",
 				},
 			},
@@ -1523,7 +1546,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 		Status: kfserving.InferenceServiceStatus{
 			URL: serviceName + ".svc.cluster.local",
 			Default: &kfserving.ComponentStatusMap{
-				constants.Predictor: &kfserving.StatusConfigurationSpec{
+				constants.Predictor: kfserving.StatusConfigurationSpec{
 					Name: "revision-v1",
 				},
 			},
@@ -1732,21 +1755,21 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 			},
 		},
 		Default: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
-			constants.Explainer: &kfserving.StatusConfigurationSpec{
+			constants.Explainer: kfserving.StatusConfigurationSpec{
 				Name:     "e-revision-v1",
 				Hostname: constants.InferenceServiceHostName(constants.DefaultExplainerServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
 		},
 		Canary: &kfserving.ComponentStatusMap{
-			constants.Predictor: &kfserving.StatusConfigurationSpec{
+			constants.Predictor: kfserving.StatusConfigurationSpec{
 				Name:     "revision-v2",
 				Hostname: constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
-			constants.Explainer: &kfserving.StatusConfigurationSpec{
+			constants.Explainer: kfserving.StatusConfigurationSpec{
 				Name:     "e-revision-v2",
 				Hostname: constants.InferenceServiceHostName(constants.CanaryExplainerServiceName(serviceKey.Name), serviceKey.Namespace, domain),
 			},
@@ -1761,12 +1784,12 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 	}, timeout).Should(gomega.BeEmpty())
 
 	// verify virtual service creation
-	virtualService := &istiov1alpha3.VirtualService{}
+	virtualService := &v1alpha3.VirtualService{}
 	g.Eventually(func() error { return c.Get(context.TODO(), virtualServiceName, virtualService) }, timeout).
 		Should(gomega.Succeed())
 
-	expectedVirtualService := &istiov1alpha3.VirtualService{
-		Spec: istiov1alpha3.VirtualServiceSpec{
+	expectedVirtualService := &v1alpha3.VirtualService{
+		Spec: istiov1alpha3.VirtualService{
 			Gateways: []string{
 				constants.KnativeIngressGateway,
 				constants.KnativeLocalGateway,
@@ -1775,51 +1798,59 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 				constants.InferenceServiceHostName(serviceName, serviceKey.Namespace, domain),
 				network.GetServiceHostname(serviceName, serviceKey.Namespace),
 			},
-			HTTP: []istiov1alpha3.HTTPRoute{
+			Http: []*istiov1alpha3.HTTPRoute{
 				{
-					Match: []istiov1alpha3.HTTPMatchRequest{
+					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeIngressGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+								},
 							},
 						},
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.PredictPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.PredictPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeLocalGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+								},
 							},
 						},
 					},
-					Route: []istiov1alpha3.HTTPRouteDestination{
+					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), serviceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: constants.LocalGatewayHost,
 							},
 							Weight: 80,
 						},
 						{
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.HeaderOperations{
+								Request: &istiov1alpha3.Headers_HeaderOperations{
 									Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.CanaryPredictorServiceName(serviceName), serviceKey.Namespace),
 									},
 								},
 							},
-							Destination: istiov1alpha3.Destination{
+							Destination: &istiov1alpha3.Destination{
 								Host: constants.LocalGatewayHost,
 							},
 							Weight: 20,
@@ -1827,51 +1858,59 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
 						Attempts:      3,
-						PerTryTimeout: "10m",
+						PerTryTimeout: istio.RetryTimeout,
 					},
 				},
 				{
-					Match: []v1alpha3.HTTPMatchRequest{
+					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.ExplainPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.ExplainPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeIngressGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain)),
+								},
 							},
 						},
 						{
-							URI: &istiov1alpha1.StringMatch{
-								Prefix: constants.ExplainPrefix(serviceName),
+							Uri: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Prefix{
+									Prefix: constants.ExplainPrefix(serviceName),
+								},
 							},
 							Gateways: []string{constants.KnativeLocalGateway},
-							Authority: &v1alpha1.StringMatch{
-								Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+							Authority: &istiov1alpha3.StringMatch{
+								MatchType: &istiov1alpha3.StringMatch_Regex{
+									Regex: constants.HostRegExp(network.GetServiceHostname(serviceKey.Name, serviceKey.Namespace)),
+								},
 							},
 						},
 					},
-					Route: []v1alpha3.HTTPRouteDestination{
+					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
-							Destination: v1alpha3.Destination{Host: constants.LocalGatewayHost},
+							Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 							Weight:      80,
-							Headers: &v1alpha3.Headers{
-								Request: &v1alpha3.HeaderOperations{Set: map[string]string{
+							Headers: &istiov1alpha3.Headers{
+								Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 									"Host": network.GetServiceHostname(constants.DefaultExplainerServiceName(serviceName), serviceKey.Namespace)}},
 							},
 						},
 						{
-							Destination: v1alpha3.Destination{Host: constants.LocalGatewayHost},
+							Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 							Weight:      20,
-							Headers: &v1alpha3.Headers{
-								Request: &v1alpha3.HeaderOperations{Set: map[string]string{
+							Headers: &istiov1alpha3.Headers{
+								Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 									"Host": network.GetServiceHostname(constants.CanaryExplainerServiceName(serviceName), serviceKey.Namespace)}},
 							},
 						},
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
 						Attempts:      3,
-						PerTryTimeout: "10m",
+						PerTryTimeout: istio.RetryTimeout,
 					},
 				},
 			},
diff --git a/pkg/controller/inferenceservice/reconcilers/knative/service_reconciler_test.go b/pkg/controller/inferenceservice/reconcilers/knative/service_reconciler_test.go
--- a/pkg/controller/inferenceservice/reconcilers/knative/service_reconciler_test.go
+++ b/pkg/controller/inferenceservice/reconcilers/knative/service_reconciler_test.go
@@ -44,9 +44,9 @@ const (
 func TestKnativeServiceReconcile(t *testing.T) {
 	g := gomega.NewGomegaWithT(t)
 
-	mgr, err := manager.New(cfg, manager.Options{})
-	stopMgr, mgrStopped := testutils.StartTestManager(mgr, g)
+	mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: "0"})
 	g.Expect(err).NotTo(gomega.HaveOccurred())
+	stopMgr, mgrStopped := testutils.StartTestManager(mgr, g)
 	c := mgr.GetClient()
 
 	defer func() {
diff --git a/pkg/controller/inferenceservice/resources/istio/virtualservice_test.go b/pkg/controller/inferenceservice/resources/istio/virtualservice_test.go
--- a/pkg/controller/inferenceservice/resources/istio/virtualservice_test.go
+++ b/pkg/controller/inferenceservice/resources/istio/virtualservice_test.go
@@ -20,12 +20,12 @@ import (
 	"github.com/google/go-cmp/cmp"
 	"github.com/kubeflow/kfserving/pkg/apis/serving/v1alpha2"
 	"github.com/kubeflow/kfserving/pkg/constants"
+	istiov1alpha3 "istio.io/api/networking/v1alpha3"
+	"istio.io/client-go/pkg/apis/networking/v1alpha3"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"knative.dev/pkg/apis"
 	duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
-	istiov1alpha1 "knative.dev/pkg/apis/istio/common/v1alpha1"
-	istiov1alpha3 "knative.dev/pkg/apis/istio/v1alpha3"
 	"knative.dev/pkg/network"
 	"testing"
 )
@@ -42,18 +42,30 @@ func TestCreateVirtualService(t *testing.T) {
 	explainerHostname := constants.InferenceServiceHostName(constants.DefaultExplainerServiceName(serviceName), namespace, domain)
 	canaryPredictorHostname := constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(serviceName), namespace, domain)
 	canaryTransformerHostname := constants.InferenceServiceHostName(constants.CanaryTransformerServiceName(serviceName), namespace, domain)
-	predictorRouteMatch := []istiov1alpha3.HTTPMatchRequest{
+	predictorRouteMatch := []*istiov1alpha3.HTTPMatchRequest{
 		{
-			URI: &istiov1alpha1.StringMatch{Prefix: "/v1/models/my-model:predict"},
-			Authority: &istiov1alpha1.StringMatch{
-				Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceName, namespace, domain)),
+			Uri: &istiov1alpha3.StringMatch{
+				MatchType: &istiov1alpha3.StringMatch_Prefix{
+					Prefix: "/v1/models/my-model:predict",
+				},
+			},
+			Authority: &istiov1alpha3.StringMatch{
+				MatchType: &istiov1alpha3.StringMatch_Regex{
+					Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceName, namespace, domain)),
+				},
 			},
 			Gateways: []string{constants.KnativeIngressGateway},
 		},
 		{
-			URI: &istiov1alpha1.StringMatch{Prefix: "/v1/models/my-model:predict"},
-			Authority: &istiov1alpha1.StringMatch{
-				Regex: constants.HostRegExp(network.GetServiceHostname(serviceName, namespace)),
+			Uri: &istiov1alpha3.StringMatch{
+				MatchType: &istiov1alpha3.StringMatch_Prefix{
+					Prefix: "/v1/models/my-model:predict",
+				},
+			},
+			Authority: &istiov1alpha3.StringMatch{
+				MatchType: &istiov1alpha3.StringMatch_Regex{
+					Regex: constants.HostRegExp(network.GetServiceHostname(serviceName, namespace)),
+				},
 			},
 			Gateways: []string{constants.KnativeLocalGateway},
 		},
@@ -63,7 +75,7 @@ func TestCreateVirtualService(t *testing.T) {
 		defaultStatus   *v1alpha2.ComponentStatusMap
 		canaryStatus    *v1alpha2.ComponentStatusMap
 		expectedStatus  *v1alpha2.VirtualServiceStatus
-		expectedService *istiov1alpha3.VirtualService
+		expectedService *v1alpha3.VirtualService
 	}{{
 		name:            "nil status should not be ready",
 		defaultStatus:   nil,
@@ -79,7 +91,7 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "predictor missing host name",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{},
 		},
 		canaryStatus:    nil,
 		expectedStatus:  createFailedStatus(PredictorHostnameUnknown, PredictorMissingMessage),
@@ -87,7 +99,7 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "found predictor",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
@@ -109,27 +121,27 @@ func TestCreateVirtualService(t *testing.T) {
 			},
 			DefaultWeight: 100,
 		},
-		expectedService: &istiov1alpha3.VirtualService{
+		expectedService: &v1alpha3.VirtualService{
 			ObjectMeta: metav1.ObjectMeta{Name: serviceName, Namespace: namespace},
-			Spec: istiov1alpha3.VirtualServiceSpec{
+			Spec: istiov1alpha3.VirtualService{
 				Hosts:    []string{serviceHostName, serviceInternalHostName},
 				Gateways: []string{constants.KnativeIngressGateway, constants.KnativeLocalGateway},
-				HTTP: []istiov1alpha3.HTTPRoute{
+				Http: []*istiov1alpha3.HTTPRoute{
 					{
 						Match: predictorRouteMatch,
-						Route: []istiov1alpha3.HTTPRouteDestination{
+						Route: []*istiov1alpha3.HTTPRouteDestination{
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      100,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), namespace)}},
 								},
 							},
 						},
 						Retries: &istiov1alpha3.HTTPRetry{
 							Attempts:      3,
-							PerTryTimeout: "10m",
+							PerTryTimeout: RetryTimeout,
 						},
 					},
 				},
@@ -138,36 +150,36 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "missing canary predictor",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: nil,
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{},
 		},
-		expectedStatus:  createFailedStatus(PredictorStatusUnknown, PredictorMissingMessage),
+		expectedStatus:  createFailedStatus(PredictorHostnameUnknown, PredictorMissingMessage),
 		expectedService: nil,
 	}, {
 		name: "canary predictor no hostname",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{},
 		},
 		expectedStatus:  createFailedStatus(PredictorHostnameUnknown, PredictorMissingMessage),
 		expectedService: nil,
 	}, {
 		name: "found default and canary predictor",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus: &v1alpha2.ComponentStatusMap{
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: canaryPredictorHostname,
 			},
 		},
@@ -189,29 +201,29 @@ func TestCreateVirtualService(t *testing.T) {
 			DefaultWeight: 80,
 			CanaryWeight:  20,
 		},
-		expectedService: &istiov1alpha3.VirtualService{
+		expectedService: &v1alpha3.VirtualService{
 			ObjectMeta: metav1.ObjectMeta{Name: serviceName, Namespace: namespace},
-			Spec: istiov1alpha3.VirtualServiceSpec{
+			Spec: istiov1alpha3.VirtualService{
 				Hosts:    []string{serviceHostName, serviceInternalHostName},
 				Gateways: []string{constants.KnativeIngressGateway, constants.KnativeLocalGateway},
-				HTTP: []istiov1alpha3.HTTPRoute{
+				Http: []*istiov1alpha3.HTTPRoute{
 					{
 						Match: predictorRouteMatch,
-						Route: []istiov1alpha3.HTTPRouteDestination{
+						Route: []*istiov1alpha3.HTTPRouteDestination{
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      80,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), namespace)},
 									},
 								},
 							},
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      20,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.CanaryPredictorServiceName(serviceName), namespace)},
 									},
 								},
@@ -219,7 +231,7 @@ func TestCreateVirtualService(t *testing.T) {
 						},
 						Retries: &istiov1alpha3.HTTPRetry{
 							Attempts:      3,
-							PerTryTimeout: "10m",
+							PerTryTimeout: RetryTimeout,
 						},
 					},
 				},
@@ -228,19 +240,19 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "nil transformer status fails with status unknown",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: nil,
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus:    nil,
-		expectedStatus:  createFailedStatus(TransformerStatusUnknown, TransformerMissingMessage),
+		expectedStatus:  createFailedStatus(TransformerHostnameUnknown, TransformerMissingMessage),
 		expectedService: nil,
 	}, {
 		name: "transformer missing host name",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: &v1alpha2.StatusConfigurationSpec{},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
@@ -250,10 +262,10 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "default transformer and predictor",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{
 				Hostname: transformerHostname,
 			},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
@@ -275,20 +287,20 @@ func TestCreateVirtualService(t *testing.T) {
 			},
 			DefaultWeight: 100,
 		},
-		expectedService: &istiov1alpha3.VirtualService{
+		expectedService: &v1alpha3.VirtualService{
 			ObjectMeta: metav1.ObjectMeta{Name: serviceName, Namespace: namespace},
-			Spec: istiov1alpha3.VirtualServiceSpec{
+			Spec: istiov1alpha3.VirtualService{
 				Hosts:    []string{serviceHostName, serviceInternalHostName},
 				Gateways: []string{constants.KnativeIngressGateway, constants.KnativeLocalGateway},
-				HTTP: []istiov1alpha3.HTTPRoute{
+				Http: []*istiov1alpha3.HTTPRoute{
 					{
 						Match: predictorRouteMatch,
-						Route: []istiov1alpha3.HTTPRouteDestination{
+						Route: []*istiov1alpha3.HTTPRouteDestination{
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      100,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultTransformerServiceName(serviceName), namespace),
 									}},
 								},
@@ -296,7 +308,7 @@ func TestCreateVirtualService(t *testing.T) {
 						},
 						Retries: &istiov1alpha3.HTTPRetry{
 							Attempts:      3,
-							PerTryTimeout: "10m",
+							PerTryTimeout: RetryTimeout,
 						},
 					},
 				},
@@ -305,16 +317,16 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "missing canary transformer",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{
 				Hostname: transformerHostname,
 			},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: &v1alpha2.StatusConfigurationSpec{},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
@@ -323,18 +335,18 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "canary & default transformer and predictor",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{
 				Hostname: transformerHostname,
 			},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus: &v1alpha2.ComponentStatusMap{
-			constants.Transformer: &v1alpha2.StatusConfigurationSpec{
+			constants.Transformer: v1alpha2.StatusConfigurationSpec{
 				Hostname: canaryTransformerHostname,
 			},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: canaryPredictorHostname,
 			},
 		},
@@ -356,35 +368,35 @@ func TestCreateVirtualService(t *testing.T) {
 			DefaultWeight: 80,
 			CanaryWeight:  20,
 		},
-		expectedService: &istiov1alpha3.VirtualService{
+		expectedService: &v1alpha3.VirtualService{
 			ObjectMeta: metav1.ObjectMeta{Name: serviceName, Namespace: namespace},
-			Spec: istiov1alpha3.VirtualServiceSpec{
+			Spec: istiov1alpha3.VirtualService{
 				Hosts:    []string{serviceHostName, serviceInternalHostName},
 				Gateways: []string{constants.KnativeIngressGateway, constants.KnativeLocalGateway},
-				HTTP: []istiov1alpha3.HTTPRoute{
+				Http: []*istiov1alpha3.HTTPRoute{
 					{
 						Match: predictorRouteMatch,
-						Route: []istiov1alpha3.HTTPRouteDestination{
+						Route: []*istiov1alpha3.HTTPRouteDestination{
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      80,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultTransformerServiceName(serviceName), namespace)}},
 								},
 							},
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      20,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.CanaryTransformerServiceName(serviceName), namespace)}},
 								},
 							},
 						},
 						Retries: &istiov1alpha3.HTTPRetry{
 							Attempts:      3,
-							PerTryTimeout: "10m",
+							PerTryTimeout: RetryTimeout,
 						},
 					},
 				},
@@ -393,19 +405,19 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "nil explainer status fails with status unknown",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Explainer: nil,
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Explainer: v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
 		canaryStatus:    nil,
-		expectedStatus:  createFailedStatus(ExplainerStatusUnknown, ExplainerMissingMessage),
+		expectedStatus:  createFailedStatus(ExplainerHostnameUnknown, ExplainerMissingMessage),
 		expectedService: nil,
 	}, {
 		name: "explainer missing host name",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Explainer: &v1alpha2.StatusConfigurationSpec{},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Explainer: v1alpha2.StatusConfigurationSpec{},
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
@@ -415,10 +427,10 @@ func TestCreateVirtualService(t *testing.T) {
 	}, {
 		name: "default explainer and predictor",
 		defaultStatus: &v1alpha2.ComponentStatusMap{
-			constants.Explainer: &v1alpha2.StatusConfigurationSpec{
+			constants.Explainer: v1alpha2.StatusConfigurationSpec{
 				Hostname: explainerHostname,
 			},
-			constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+			constants.Predictor: v1alpha2.StatusConfigurationSpec{
 				Hostname: predictorHostname,
 			},
 		},
@@ -440,20 +452,20 @@ func TestCreateVirtualService(t *testing.T) {
 			},
 			DefaultWeight: 100,
 		},
-		expectedService: &istiov1alpha3.VirtualService{
+		expectedService: &v1alpha3.VirtualService{
 			ObjectMeta: metav1.ObjectMeta{Name: serviceName, Namespace: namespace},
-			Spec: istiov1alpha3.VirtualServiceSpec{
+			Spec: istiov1alpha3.VirtualService{
 				Hosts:    []string{serviceHostName, serviceInternalHostName},
 				Gateways: []string{constants.KnativeIngressGateway, constants.KnativeLocalGateway},
-				HTTP: []istiov1alpha3.HTTPRoute{
+				Http: []*istiov1alpha3.HTTPRoute{
 					{
 						Match: predictorRouteMatch,
-						Route: []istiov1alpha3.HTTPRouteDestination{
+						Route: []*istiov1alpha3.HTTPRouteDestination{
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      100,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), namespace)},
 									},
 								},
@@ -461,32 +473,44 @@ func TestCreateVirtualService(t *testing.T) {
 						},
 						Retries: &istiov1alpha3.HTTPRetry{
 							Attempts:      3,
-							PerTryTimeout: "10m",
+							PerTryTimeout: RetryTimeout,
 						},
 					},
 					{
-						Match: []istiov1alpha3.HTTPMatchRequest{
+						Match: []*istiov1alpha3.HTTPMatchRequest{
 							{
-								URI: &istiov1alpha1.StringMatch{Prefix: "/v1/models/my-model:explain"},
-								Authority: &istiov1alpha1.StringMatch{
-									Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceName, namespace, domain)),
+								Uri: &istiov1alpha3.StringMatch{
+									MatchType: &istiov1alpha3.StringMatch_Prefix{
+										Prefix: "/v1/models/my-model:explain",
+									},
+								},
+								Authority: &istiov1alpha3.StringMatch{
+									MatchType: &istiov1alpha3.StringMatch_Regex{
+										Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceName, namespace, domain)),
+									},
 								},
 								Gateways: []string{constants.KnativeIngressGateway},
 							},
 							{
-								URI: &istiov1alpha1.StringMatch{Prefix: "/v1/models/my-model:explain"},
-								Authority: &istiov1alpha1.StringMatch{
-									Regex: constants.HostRegExp(network.GetServiceHostname(serviceName, namespace)),
+								Uri: &istiov1alpha3.StringMatch{
+									MatchType: &istiov1alpha3.StringMatch_Prefix{
+										Prefix: "/v1/models/my-model:explain",
+									},
+								},
+								Authority: &istiov1alpha3.StringMatch{
+									MatchType: &istiov1alpha3.StringMatch_Regex{
+										Regex: constants.HostRegExp(network.GetServiceHostname(serviceName, namespace)),
+									},
 								},
 								Gateways: []string{constants.KnativeLocalGateway},
 							},
 						},
-						Route: []istiov1alpha3.HTTPRouteDestination{
+						Route: []*istiov1alpha3.HTTPRouteDestination{
 							{
-								Destination: istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost},
 								Weight:      100,
 								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.HeaderOperations{Set: map[string]string{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
 										"Host": network.GetServiceHostname(constants.DefaultExplainerServiceName(serviceName), namespace)},
 									},
 								},
@@ -494,7 +518,7 @@ func TestCreateVirtualService(t *testing.T) {
 						},
 						Retries: &istiov1alpha3.HTTPRetry{
 							Attempts:      3,
-							PerTryTimeout: "10m",
+							PerTryTimeout: RetryTimeout,
 						},
 					},
 				},
diff --git a/pkg/controller/inferenceservice/resources/knative/service_test.go b/pkg/controller/inferenceservice/resources/knative/service_test.go
--- a/pkg/controller/inferenceservice/resources/knative/service_test.go
+++ b/pkg/controller/inferenceservice/resources/knative/service_test.go
@@ -215,7 +215,7 @@ func TestInferenceServiceToKnativeService(t *testing.T) {
 				},
 				Status: v1alpha2.InferenceServiceStatus{
 					Default: &v1alpha2.ComponentStatusMap{
-						constants.Predictor: &v1alpha2.StatusConfigurationSpec{
+						constants.Predictor: v1alpha2.StatusConfigurationSpec{
 							Name: "v1",
 						},
 					},
diff --git a/pkg/testing/envtest_setup.go b/pkg/testing/envtest_setup.go
--- a/pkg/testing/envtest_setup.go
+++ b/pkg/testing/envtest_setup.go
@@ -17,13 +17,13 @@ limitations under the License.
 package testing
 
 import (
+	"istio.io/client-go/pkg/apis/networking/v1alpha3"
 	"path/filepath"
 	"sync"
 
 	"github.com/kubeflow/kfserving/pkg/apis/serving/v1alpha2"
 	"github.com/onsi/gomega"
 	"k8s.io/client-go/kubernetes/scheme"
-	istiov1alpha3 "knative.dev/pkg/apis/istio/v1alpha3"
 	knservingv1 "knative.dev/serving/pkg/apis/serving/v1"
 	"sigs.k8s.io/controller-runtime/pkg/envtest"
 	"sigs.k8s.io/controller-runtime/pkg/manager"
@@ -38,9 +38,9 @@ func SetupEnvTest() *envtest.Environment {
 		// The relative paths must be provided for each level of test nesting
 		// This code should be illegal
 		CRDDirectoryPaths: []string{
-			filepath.Join("..", "..", "..", "..", "..", "config", "default", "crds"),
+			filepath.Join("..", "..", "..", "..", "..", "config", "default", "crds", "base"),
 			filepath.Join("..", "..", "..", "..", "..", "test", "crds"),
-			filepath.Join("..", "..", "..", "config", "default", "crds"),
+			filepath.Join("..", "..", "..", "config", "default", "crds", "base"),
 			filepath.Join("..", "..", "..", "test", "crds"),
 		},
 	}
@@ -55,7 +55,7 @@ func SetupEnvTest() *envtest.Environment {
 		log.Error(err, "Failed to add knative serving scheme")
 	}
 
-	if err = istiov1alpha3.SchemeBuilder.AddToScheme(scheme.Scheme); err != nil {
+	if err = v1alpha3.SchemeBuilder.AddToScheme(scheme.Scheme); err != nil {
 		log.Error(err, "Failed to add istio scheme")
 	}
 	return t
diff --git a/test/e2e/common/utils.py b/test/e2e/common/utils.py
--- a/test/e2e/common/utils.py
+++ b/test/e2e/common/utils.py
@@ -28,6 +28,8 @@
 
 def predict(service_name, input_json):
     isvc = KFServing.get(service_name, namespace=KFSERVING_TEST_NAMESPACE)
+    # temporary sleep until this is fixed https://github.com/kubeflow/kfserving/issues/604
+    time.sleep(10)
     api_instance = client.CoreV1Api(client.ApiClient())
     service = api_instance.read_namespaced_service("istio-ingressgateway", "istio-system", exact='true')
     cluster_ip = service.status.load_balancer.ingress[0].ip
diff --git a/test/e2e/transformer/test_transformer.py b/test/e2e/transformer/test_transformer.py
--- a/test/e2e/transformer/test_transformer.py
+++ b/test/e2e/transformer/test_transformer.py
@@ -61,7 +61,12 @@ def test_transformer():
                                     spec=V1alpha2InferenceServiceSpec(default=default_endpoint_spec))
 
     KFServing.create(isvc)
-    KFServing.wait_isvc_ready(service_name, namespace=KFSERVING_TEST_NAMESPACE)
+    try:
+        KFServing.wait_isvc_ready(service_name, namespace=KFSERVING_TEST_NAMESPACE)
+    except RuntimeError as e:
+        print(KFServing.api_instance.get_namespaced_custom_object("serving.knative.dev", "v1", KFSERVING_TEST_NAMESPACE,
+                                                                  "services", service_name + "-predictor-default"))
+        raise e
     probs = predict(service_name, './data/transformer.json')
     assert(np.argmax(probs) == 3)
     KFServing.delete(service_name, KFSERVING_TEST_NAMESPACE)
diff --git a/test/scripts/run-e2e-tests.sh b/test/scripts/run-e2e-tests.sh
--- a/test/scripts/run-e2e-tests.sh
+++ b/test/scripts/run-e2e-tests.sh
@@ -28,7 +28,7 @@ REGISTRY="${GCP_REGISTRY}"
 ISTIO_VERSION="1.3.1"
 KNATIVE_VERSION="v0.10.0"
 KUBECTL_VERSION="v1.14.0"
-
+CERT_MANAGER_VERSION="v0.12.0"
 # Check and wait for istio/knative/kfserving pod started normally.
 waiting_pod_running(){
     namespace=$1
@@ -122,6 +122,15 @@ kubectl apply --filename https://github.com/knative/serving/releases/download/${
 echo "Waiting for knative started ..."
 waiting_pod_running "knative-serving"
 
+echo "Installing cert manager ..."
+kubectl create namespace cert-manager
+sleep 2
+kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/${CERT_MANAGER_VERSION}/cert-manager.yaml
+
+echo "Waiting for cert manager started ..."
+waiting_pod_running "cert-manager"
+sleep 120  # Wait for webhook install finished totally.
+
 echo "Install KFServing ..."
 export GOPATH="$HOME/go"
 export PATH="${PATH}:${GOPATH}/bin"
diff --git a/vendor/k8s.io/client-go/testing/actions.go b/vendor/k8s.io/client-go/testing/actions.go
--- a/vendor/k8s.io/client-go/testing/actions.go
+++ b/vendor/k8s.io/client-go/testing/actions.go
@@ -26,6 +26,7 @@ import (
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/types"
 )
 
 func NewRootGetAction(resource schema.GroupVersionResource, name string) GetActionImpl {
@@ -152,45 +153,49 @@ func NewUpdateAction(resource schema.GroupVersionResource, namespace string, obj
 	return action
 }
 
-func NewRootPatchAction(resource schema.GroupVersionResource, name string, patch []byte) PatchActionImpl {
+func NewRootPatchAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte) PatchActionImpl {
 	action := PatchActionImpl{}
 	action.Verb = "patch"
 	action.Resource = resource
 	action.Name = name
+	action.PatchType = pt
 	action.Patch = patch
 
 	return action
 }
 
-func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, patch []byte) PatchActionImpl {
+func NewPatchAction(resource schema.GroupVersionResource, namespace string, name string, pt types.PatchType, patch []byte) PatchActionImpl {
 	action := PatchActionImpl{}
 	action.Verb = "patch"
 	action.Resource = resource
 	action.Namespace = namespace
 	action.Name = name
+	action.PatchType = pt
 	action.Patch = patch
 
 	return action
 }
 
-func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, patch []byte, subresources ...string) PatchActionImpl {
+func NewRootPatchSubresourceAction(resource schema.GroupVersionResource, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl {
 	action := PatchActionImpl{}
 	action.Verb = "patch"
 	action.Resource = resource
 	action.Subresource = path.Join(subresources...)
 	action.Name = name
+	action.PatchType = pt
 	action.Patch = patch
 
 	return action
 }
 
-func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, patch []byte, subresources ...string) PatchActionImpl {
+func NewPatchSubresourceAction(resource schema.GroupVersionResource, namespace, name string, pt types.PatchType, patch []byte, subresources ...string) PatchActionImpl {
 	action := PatchActionImpl{}
 	action.Verb = "patch"
 	action.Resource = resource
 	action.Subresource = path.Join(subresources...)
 	action.Namespace = namespace
 	action.Name = name
+	action.PatchType = pt
 	action.Patch = patch
 
 	return action
@@ -396,6 +401,7 @@ type DeleteCollectionAction interface {
 type PatchAction interface {
 	Action
 	GetName() string
+	GetPatchType() types.PatchType
 	GetPatch() []byte
 }
 
@@ -537,8 +543,9 @@ func (a UpdateActionImpl) DeepCopy() Action {
 
 type PatchActionImpl struct {
 	ActionImpl
-	Name  string
-	Patch []byte
+	Name      string
+	PatchType types.PatchType
+	Patch     []byte
 }
 
 func (a PatchActionImpl) GetName() string {
@@ -549,12 +556,17 @@ func (a PatchActionImpl) GetPatch() []byte {
 	return a.Patch
 }
 
+func (a PatchActionImpl) GetPatchType() types.PatchType {
+	return a.PatchType
+}
+
 func (a PatchActionImpl) DeepCopy() Action {
 	patch := make([]byte, len(a.Patch))
 	copy(patch, a.Patch)
 	return PatchActionImpl{
 		ActionImpl: a.ActionImpl.DeepCopy().(ActionImpl),
 		Name:       a.Name,
+		PatchType:  a.PatchType,
 		Patch:      patch,
 	}
 }
diff --git a/vendor/k8s.io/client-go/testing/fake.go b/vendor/k8s.io/client-go/testing/fake.go
--- a/vendor/k8s.io/client-go/testing/fake.go
+++ b/vendor/k8s.io/client-go/testing/fake.go
@@ -131,13 +131,14 @@ func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.
 	c.Lock()
 	defer c.Unlock()
 
+	actionCopy := action.DeepCopy()
 	c.actions = append(c.actions, action.DeepCopy())
 	for _, reactor := range c.ReactionChain {
-		if !reactor.Handles(action) {
+		if !reactor.Handles(actionCopy) {
 			continue
 		}
 
-		handled, ret, err := reactor.React(action.DeepCopy())
+		handled, ret, err := reactor.React(actionCopy)
 		if !handled {
 			continue
 		}
@@ -154,13 +155,14 @@ func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) {
 	c.Lock()
 	defer c.Unlock()
 
+	actionCopy := action.DeepCopy()
 	c.actions = append(c.actions, action.DeepCopy())
 	for _, reactor := range c.WatchReactionChain {
-		if !reactor.Handles(action) {
+		if !reactor.Handles(actionCopy) {
 			continue
 		}
 
-		handled, ret, err := reactor.React(action.DeepCopy())
+		handled, ret, err := reactor.React(actionCopy)
 		if !handled {
 			continue
 		}
@@ -177,13 +179,14 @@ func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper {
 	c.Lock()
 	defer c.Unlock()
 
+	actionCopy := action.DeepCopy()
 	c.actions = append(c.actions, action.DeepCopy())
 	for _, reactor := range c.ProxyReactionChain {
-		if !reactor.Handles(action) {
+		if !reactor.Handles(actionCopy) {
 			continue
 		}
 
-		handled, ret, err := reactor.React(action.DeepCopy())
+		handled, ret, err := reactor.React(actionCopy)
 		if !handled || err != nil {
 			continue
 		}
diff --git a/vendor/k8s.io/client-go/testing/fixture.go b/vendor/k8s.io/client-go/testing/fixture.go
--- a/vendor/k8s.io/client-go/testing/fixture.go
+++ b/vendor/k8s.io/client-go/testing/fixture.go
@@ -20,11 +20,13 @@ import (
 	"fmt"
 	"sync"
 
+	jsonpatch "github.com/evanphx/json-patch"
 	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/json"
 	"k8s.io/apimachinery/pkg/util/strategicpatch"
 	"k8s.io/apimachinery/pkg/watch"
@@ -129,23 +131,46 @@ func ObjectReaction(tracker ObjectTracker) ReactionFunc {
 		case PatchActionImpl:
 			obj, err := tracker.Get(gvr, ns, action.GetName())
 			if err != nil {
-				// object is not registered
-				return false, nil, err
+				return true, nil, err
 			}
 
 			old, err := json.Marshal(obj)
 			if err != nil {
 				return true, nil, err
 			}
-			// Only supports strategic merge patch
-			// TODO: Add support for other Patch types
-			mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj)
-			if err != nil {
-				return true, nil, err
-			}
 
-			if err = json.Unmarshal(mergedByte, obj); err != nil {
-				return true, nil, err
+			switch action.GetPatchType() {
+			case types.JSONPatchType:
+				patch, err := jsonpatch.DecodePatch(action.GetPatch())
+				if err != nil {
+					return true, nil, err
+				}
+				modified, err := patch.Apply(old)
+				if err != nil {
+					return true, nil, err
+				}
+				if err = json.Unmarshal(modified, obj); err != nil {
+					return true, nil, err
+				}
+			case types.MergePatchType:
+				modified, err := jsonpatch.MergePatch(old, action.GetPatch())
+				if err != nil {
+					return true, nil, err
+				}
+
+				if err := json.Unmarshal(modified, obj); err != nil {
+					return true, nil, err
+				}
+			case types.StrategicMergePatchType:
+				mergedByte, err := strategicpatch.StrategicMergePatch(old, action.GetPatch(), obj)
+				if err != nil {
+					return true, nil, err
+				}
+				if err = json.Unmarshal(mergedByte, obj); err != nil {
+					return true, nil, err
+				}
+			default:
+				return true, nil, fmt.Errorf("PatchType is not supported")
 			}
 
 			if err = tracker.Update(gvr, obj, ns); err != nil {
@@ -322,8 +347,10 @@ func (t *tracker) getWatches(gvr schema.GroupVersionResource, ns string) []*watc
 		if w := t.watchers[gvr][ns]; w != nil {
 			watches = append(watches, w...)
 		}
-		if w := t.watchers[gvr][""]; w != nil {
-			watches = append(watches, w...)
+		if ns != metav1.NamespaceAll {
+			if w := t.watchers[gvr][metav1.NamespaceAll]; w != nil {
+				watches = append(watches, w...)
+			}
 		}
 	}
 	return watches
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/HEAD b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/HEAD
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/HEAD
@@ -0,0 +1 @@
+../../../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/dev.config b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/dev.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/dev.config
@@ -0,0 +1 @@
+../../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/prod.config b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/prod.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/prod.config
@@ -0,0 +1 @@
+../../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/refs b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/refs
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/dataplane-probe/continuous/kodata/refs
@@ -0,0 +1 @@
+../../../../../../.git/refs/
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/HEAD b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/HEAD
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/HEAD
@@ -0,0 +1 @@
+../../../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/dev.config b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/dev.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/dev.config
@@ -0,0 +1 @@
+../../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/prod.config b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/prod.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/prod.config
@@ -0,0 +1 @@
+../../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/refs b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/refs
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/deployment-probe/continuous/kodata/refs
@@ -0,0 +1 @@
+../../../../../../.git/refs/
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/HEAD b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/HEAD
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/HEAD
@@ -0,0 +1 @@
+../../../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/dev.config b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/dev.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/dev.config
@@ -0,0 +1 @@
+../../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/prod.config b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/prod.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/prod.config
@@ -0,0 +1 @@
+../../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/refs b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/refs
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/load-test/continuous/kodata/refs
@@ -0,0 +1 @@
+../../../../../../.git/refs/
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/HEAD b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/HEAD
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/HEAD
@@ -0,0 +1 @@
+../../../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/dev.config b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/dev.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/dev.config
@@ -0,0 +1 @@
+../../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/prod.config b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/prod.config
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/prod.config
@@ -0,0 +1 @@
+../../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/refs b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/refs
new file mode 120000
--- /dev/null
+++ b/vendor/knative.dev/serving/test/performance/benchmarks/scale-from-zero/continuous/kodata/refs
@@ -0,0 +1 @@
+../../../../../../.git/refs/
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/HEAD b/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/HEAD
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/HEAD
+++ /dev/null
@@ -1 +0,0 @@
-../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/dev.config b/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/dev.config
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/dev.config
+++ /dev/null
@@ -1 +0,0 @@
-../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/prod.config b/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/prod.config
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/prod.config
+++ /dev/null
@@ -1 +0,0 @@
-../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/refs b/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/refs
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/dataplane-probe/kodata/refs
+++ /dev/null
@@ -1 +0,0 @@
-../../../../.git/refs
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/HEAD b/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/HEAD
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/HEAD
+++ /dev/null
@@ -1 +0,0 @@
-../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/dev.config b/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/dev.config
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/dev.config
+++ /dev/null
@@ -1 +0,0 @@
-../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/prod.config b/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/prod.config
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/prod.config
+++ /dev/null
@@ -1 +0,0 @@
-../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/refs b/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/refs
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/deployment-probe/kodata/refs
+++ /dev/null
@@ -1 +0,0 @@
-../../../../.git/refs
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/load-test/kodata/HEAD b/vendor/knative.dev/serving/test/performance/load-test/kodata/HEAD
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/load-test/kodata/HEAD
+++ /dev/null
@@ -1 +0,0 @@
-../../../../.git/HEAD
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/load-test/kodata/dev.config b/vendor/knative.dev/serving/test/performance/load-test/kodata/dev.config
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/load-test/kodata/dev.config
+++ /dev/null
@@ -1 +0,0 @@
-../dev.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/load-test/kodata/prod.config b/vendor/knative.dev/serving/test/performance/load-test/kodata/prod.config
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/load-test/kodata/prod.config
+++ /dev/null
@@ -1 +0,0 @@
-../prod.config
\ No newline at end of file
diff --git a/vendor/knative.dev/serving/test/performance/load-test/kodata/refs b/vendor/knative.dev/serving/test/performance/load-test/kodata/refs
deleted file mode 120000
--- a/vendor/knative.dev/serving/test/performance/load-test/kodata/refs
+++ /dev/null
@@ -1 +0,0 @@
-../../../../.git/refs
\ No newline at end of file