Repository: kserve/kserve

Issue:
custom image has 2 interfaces, how to access them?
/kind bug
If the custom image has one interface, it can be accessed by set route '/v1/models/{servername}:predict'. But if the custom image has >=2 interfaces, how to access others?
This is a custom flask server example, i can call `hello_world` by `curl http://xxx//v1/models/my-custom-sample:predict`, but i cannot call `hello_world_test`.
```python
import os

from flask import Flask

app = Flask(__name__)

@app.route('/v1/models/my-custom-sample:test')
def hello_world_test():
    target = os.environ.get('TARGET', 'World')
    return 'test Hello {}!\n'.format(target)

@app.route('/v1/models/my-custom-sample:predict')
def hello_world():
    target = os.environ.get('TARGET', 'World')
    return 'Hello {}!\n'.format(target)

if __name__ == "__main__":
    app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))

```

**What did you expect to happen:**
I want to access the 2 inferfaces both.




Discussion:
Issue-Label Bot is automatically applying the labels:

| Label  | Probability |
| ------------- | ------------- |
| question | 0.82 |

Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback! 
Links: [app homepage](https://github.com/marketplace/issue-label-bot), [dashboard](https://github.com/marketplace/issue-label-botdata/kubeflow/kfserving) and [code](https://github.com/hamelsmu/MLapp) for this bot.
As discussed, we can possibly introduce an annotation for the custom endpoint and make the top level virtual service configurable.
> As discussed, we can possibly introduce an annotation for the custom endpoint and make the top level virtual service configurable.

good idea. I will give a try  in next week. do you have some else suggestions?
Issue-Label Bot is automatically applying the labels:

| Label  | Probability |
| ------------- | ------------- |
| area/engprod | 0.67 |

Please mark this comment with :thumbsup: or :thumbsdown: to give our bot feedback! 
Links: [app homepage](https://github.com/marketplace/issue-label-bot), [dashboard](https://github.com/marketplace/issue-label-botdata/kubeflow/kfserving) and [code](https://github.com/hamelsmu/MLapp) for this bot.

Resolving patch:
diff --git a/docs/samples/custom/customized-urls/app.py b/docs/samples/custom/customized-urls/app.py
new file mode 100644
--- /dev/null
+++ b/docs/samples/custom/customized-urls/app.py
@@ -0,0 +1,17 @@
+import os
+
+from flask import Flask
+
+app = Flask(__name__)
+@app.route('/customized/urls/demo/test/1')
+def customized_urls_test():
+    target = os.environ.get('TARGET', 'World')
+    return 'Hello {}. Func customized_urls_test is called!\n'.format(target)
+
+@app.route('/v1/models/customized-sample:predict')
+def hello_world():
+    target = os.environ.get('TARGET', 'World')
+    return 'Hello {}!\n'.format(target)
+
+if __name__ == "__main__":
+    app.run(debug=True,host='0.0.0.0',port=int(os.environ.get('PORT', 8080)))


Test patch:
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
@@ -213,7 +213,7 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 	updateDefault.Status.LatestCreatedRevisionName = "revision-v1"
 	updateDefault.Status.LatestReadyRevisionName = "revision-v1"
 	updateDefault.Status.URL, _ = apis.ParseURL(
-		constants.InferenceServiceURL("http", constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain))
+		"http://" + constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain))
 	updateDefault.Status.Conditions = duckv1.Conditions{
 		{
 			Type:   knservingv1.ServiceConditionReady,
@@ -241,11 +241,6 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 				{
 					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeIngressGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -254,11 +249,6 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 							},
 						},
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeLocalGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -311,7 +301,7 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 				},
 			},
 		},
-		URL: constants.InferenceServiceURL("http", serviceKey.Name, serviceKey.Namespace, domain),
+		URL: "http://" + constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain),
 		Address: &duckv1beta1.Addressable{
 			URL: &apis.URL{
 				Scheme: "http",
@@ -395,7 +385,7 @@ func TestInferenceServiceWithOnlyPredictor(t *testing.T) {
 	succedingService.Status.LatestCreatedRevisionName = "revision-v3"
 	succedingService.Status.LatestReadyRevisionName = "revision-v3"
 	succedingService.Status.URL, _ = apis.ParseURL(
-		constants.InferenceServiceURL("http", constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain))
+		"http://" + constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceKey.Name), serviceKey.Namespace, domain))
 	succedingService.Status.Conditions = duckv1.Conditions{
 		{
 			Type:   knservingv1.ServiceConditionReady,
@@ -624,7 +614,7 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 	updateDefault := defaultService.DeepCopy()
 	updateDefault.Status.LatestCreatedRevisionName = "revision-v1"
 	updateDefault.Status.LatestReadyRevisionName = "revision-v1"
-	updateDefault.Status.URL, _ = apis.ParseURL(constants.InferenceServiceURL("http", constants.DefaultPredictorServiceName(canaryServiceKey.Name),
+	updateDefault.Status.URL, _ = apis.ParseURL("http://" + constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(canaryServiceKey.Name),
 		canaryServiceKey.Namespace, domain))
 	updateDefault.Status.Conditions = duckv1.Conditions{
 		{
@@ -639,7 +629,7 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 	updateCanary.Status.LatestCreatedRevisionName = "revision-v2"
 	updateCanary.Status.LatestReadyRevisionName = "revision-v2"
 	updateCanary.Status.URL, _ = apis.ParseURL(
-		constants.InferenceServiceURL("http", constants.CanaryPredictorServiceName(canaryServiceKey.Name), canaryServiceKey.Namespace, domain))
+		"http://" + constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(canaryServiceKey.Name), canaryServiceKey.Namespace, domain))
 	updateCanary.Status.Conditions = duckv1.Conditions{
 		{
 			Type:   knservingv1.ServiceConditionReady,
@@ -672,7 +662,7 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 				},
 			},
 		},
-		URL: constants.InferenceServiceURL("http", canaryServiceKey.Name,
+		URL: "http://" + constants.InferenceServiceHostName(canaryServiceKey.Name,
 			canaryService.Namespace, domain),
 		Address: &duckv1beta1.Addressable{
 			URL: &apis.URL{
@@ -724,11 +714,6 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 				{
 					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeIngressGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -737,11 +722,6 @@ func TestInferenceServiceWithDefaultAndCanaryPredictor(t *testing.T) {
 							},
 						},
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeLocalGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -891,7 +871,7 @@ func TestCanaryDelete(t *testing.T) {
 	updateDefault.Status.LatestCreatedRevisionName = "revision-v1"
 	updateDefault.Status.LatestReadyRevisionName = "revision-v1"
 	updateDefault.Status.URL, _ = apis.ParseURL(
-		constants.InferenceServiceURL("http", constants.DefaultPredictorServiceName(serviceName), namespace, domain))
+		"http://" + constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceName), namespace, domain))
 	updateDefault.Status.Conditions = duckv1.Conditions{
 		{
 			Type:   knservingv1.ServiceConditionReady,
@@ -905,7 +885,7 @@ func TestCanaryDelete(t *testing.T) {
 	updateCanary.Status.LatestCreatedRevisionName = "revision-v2"
 	updateCanary.Status.LatestReadyRevisionName = "revision-v2"
 	updateCanary.Status.URL, _ = apis.ParseURL(
-		constants.InferenceServiceURL("http", constants.CanaryPredictorServiceName(serviceName), namespace, domain))
+		"http://" + constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(serviceName), namespace, domain))
 	updateCanary.Status.Conditions = duckv1.Conditions{
 		{
 			Type:   knservingv1.ServiceConditionReady,
@@ -938,7 +918,7 @@ func TestCanaryDelete(t *testing.T) {
 				},
 			},
 		},
-		URL: constants.InferenceServiceURL("http", serviceName, namespace, domain),
+		URL: "http://" + constants.InferenceServiceHostName(serviceName, namespace, domain),
 		Address: &duckv1beta1.Addressable{
 			URL: &apis.URL{
 				Scheme: "http",
@@ -1024,7 +1004,7 @@ func TestCanaryDelete(t *testing.T) {
 				},
 			},
 		},
-		URL: constants.InferenceServiceURL("http", serviceName, namespace, domain),
+		URL: "http://" + constants.InferenceServiceHostName(serviceName, namespace, domain),
 		Address: &duckv1beta1.Addressable{
 			URL: &apis.URL{
 				Scheme: "http",
@@ -1332,7 +1312,7 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 		},
 		Traffic:       80,
 		CanaryTraffic: 20,
-		URL:           constants.InferenceServiceURL("http", serviceKey.Name, serviceKey.Namespace, domain),
+		URL:           "http://" + constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain),
 		Address: &duckv1beta1.Addressable{
 			URL: &apis.URL{
 				Scheme: "http",
@@ -1388,11 +1368,6 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 				{
 					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeIngressGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -1401,11 +1376,6 @@ func TestInferenceServiceWithTransformer(t *testing.T) {
 							},
 						},
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeLocalGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -1831,7 +1801,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 		updateCanary.Status.LatestCreatedRevisionName = "revision-v2"
 		updateCanary.Status.LatestReadyRevisionName = "revision-v2"
 		updateCanary.Status.URL, _ = apis.ParseURL(
-			constants.InferenceServiceURL("http", constants.CanaryPredictorServiceName(serviceName), namespace, domain))
+			"http://" + constants.InferenceServiceHostName(constants.CanaryPredictorServiceName(serviceName), namespace, domain))
 		updateCanary.Status.Conditions = duckv1.Conditions{
 			{
 				Type:   knservingv1.ServiceConditionReady,
@@ -1848,7 +1818,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 		updateDefault.Status.LatestCreatedRevisionName = "e-revision-v1"
 		updateDefault.Status.LatestReadyRevisionName = "e-revision-v1"
 		updateDefault.Status.URL, _ = apis.ParseURL(
-			constants.InferenceServiceURL("http", constants.DefaultExplainerServiceName(serviceName), namespace, domain))
+			"http://" + constants.InferenceServiceHostName(constants.DefaultExplainerServiceName(serviceName), namespace, domain))
 		updateDefault.Status.Conditions = duckv1.Conditions{
 			{
 				Type:   knservingv1.ServiceConditionReady,
@@ -1862,7 +1832,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 		updateCanary.Status.LatestCreatedRevisionName = "e-revision-v2"
 		updateCanary.Status.LatestReadyRevisionName = "e-revision-v2"
 		updateCanary.Status.URL, _ = apis.ParseURL(
-			constants.InferenceServiceURL("http", constants.CanaryExplainerServiceName(serviceName), namespace, domain))
+			"http://" + constants.InferenceServiceHostName(constants.CanaryExplainerServiceName(serviceName), namespace, domain))
 		updateCanary.Status.Conditions = duckv1.Conditions{
 			{
 				Type:   knservingv1.ServiceConditionReady,
@@ -1910,7 +1880,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 		},
 		Traffic:       80,
 		CanaryTraffic: 20,
-		URL:           constants.InferenceServiceURL("http", serviceKey.Name, serviceKey.Namespace, domain),
+		URL:           "http://" + constants.InferenceServiceHostName(serviceKey.Name, serviceKey.Namespace, domain),
 		Address: &duckv1beta1.Addressable{
 			URL: &apis.URL{
 				Scheme: "http",
@@ -1968,7 +1938,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 						{
 							Uri: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
+									Regex: constants.ExplainPrefix(),
 								},
 							},
 							Gateways: []string{constants.KnativeIngressGateway},
@@ -1981,7 +1951,7 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 						{
 							Uri: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.PredictPrefix(),
+									Regex: constants.ExplainPrefix(),
 								},
 							},
 							Gateways: []string{constants.KnativeLocalGateway},
@@ -1994,32 +1964,20 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 					},
 					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
+							Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost, Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort}},
+							Weight:      80,
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.Headers_HeaderOperations{
-									Set: map[string]string{
-										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), serviceKey.Namespace),
-									},
-								},
-							},
-							Destination: &istiov1alpha3.Destination{
-								Host: constants.LocalGatewayHost,
-								Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort},
+								Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
+									"Host": network.GetServiceHostname(constants.DefaultExplainerServiceName(serviceName), serviceKey.Namespace)}},
 							},
-							Weight: 80,
 						},
 						{
+							Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost, Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort}},
+							Weight:      20,
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.Headers_HeaderOperations{
-									Set: map[string]string{
-										"Host": network.GetServiceHostname(constants.CanaryPredictorServiceName(serviceName), serviceKey.Namespace),
-									},
-								},
-							},
-							Destination: &istiov1alpha3.Destination{
-								Host: constants.LocalGatewayHost,
-								Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort},
+								Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
+									"Host": network.GetServiceHostname(constants.CanaryExplainerServiceName(serviceName), serviceKey.Namespace)}},
 							},
-							Weight: 20,
 						},
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
@@ -2030,11 +1988,6 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 				{
 					Match: []*istiov1alpha3.HTTPMatchRequest{
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.ExplainPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeIngressGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -2043,11 +1996,6 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 							},
 						},
 						{
-							Uri: &istiov1alpha3.StringMatch{
-								MatchType: &istiov1alpha3.StringMatch_Regex{
-									Regex: constants.ExplainPrefix(),
-								},
-							},
 							Gateways: []string{constants.KnativeLocalGateway},
 							Authority: &istiov1alpha3.StringMatch{
 								MatchType: &istiov1alpha3.StringMatch_Regex{
@@ -2058,20 +2006,32 @@ func TestInferenceServiceWithExplainer(t *testing.T) {
 					},
 					Route: []*istiov1alpha3.HTTPRouteDestination{
 						{
-							Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost, Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort}},
-							Weight:      80,
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
-									"Host": network.GetServiceHostname(constants.DefaultExplainerServiceName(serviceName), serviceKey.Namespace)}},
+								Request: &istiov1alpha3.Headers_HeaderOperations{
+									Set: map[string]string{
+										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), serviceKey.Namespace),
+									},
+								},
+							},
+							Destination: &istiov1alpha3.Destination{
+								Host: constants.LocalGatewayHost,
+								Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort},
 							},
+							Weight: 80,
 						},
 						{
-							Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost, Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort}},
-							Weight:      20,
 							Headers: &istiov1alpha3.Headers{
-								Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
-									"Host": network.GetServiceHostname(constants.CanaryExplainerServiceName(serviceName), serviceKey.Namespace)}},
+								Request: &istiov1alpha3.Headers_HeaderOperations{
+									Set: map[string]string{
+										"Host": network.GetServiceHostname(constants.CanaryPredictorServiceName(serviceName), serviceKey.Namespace),
+									},
+								},
 							},
+							Destination: &istiov1alpha3.Destination{
+								Host: constants.LocalGatewayHost,
+								Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort},
+							},
+							Weight: 20,
 						},
 					},
 					Retries: &istiov1alpha3.HTTPRetry{
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
@@ -34,7 +34,7 @@ func TestCreateVirtualService(t *testing.T) {
 	serviceName := "my-model"
 	namespace := "test"
 	domain := "example.com"
-	expectedURL := constants.InferenceServiceURL("http", serviceName, namespace, domain)
+	expectedURL := "http://" + constants.InferenceServiceHostName(serviceName, namespace, domain)
 	serviceHostName := constants.InferenceServiceHostName(serviceName, namespace, domain)
 	serviceInternalHostName := network.GetServiceHostname(serviceName, namespace)
 	predictorHostname := constants.InferenceServiceHostName(constants.DefaultPredictorServiceName(serviceName), namespace, domain)
@@ -44,11 +44,6 @@ func TestCreateVirtualService(t *testing.T) {
 	canaryTransformerHostname := constants.InferenceServiceHostName(constants.CanaryTransformerServiceName(serviceName), namespace, domain)
 	predictorRouteMatch := []*istiov1alpha3.HTTPMatchRequest{
 		{
-			Uri: &istiov1alpha3.StringMatch{
-				MatchType: &istiov1alpha3.StringMatch_Regex{
-					Regex: constants.PredictPrefix(),
-				},
-			},
 			Authority: &istiov1alpha3.StringMatch{
 				MatchType: &istiov1alpha3.StringMatch_Regex{
 					Regex: constants.HostRegExp(constants.InferenceServiceHostName(serviceName, namespace, domain)),
@@ -57,11 +52,6 @@ func TestCreateVirtualService(t *testing.T) {
 			Gateways: []string{constants.KnativeIngressGateway},
 		},
 		{
-			Uri: &istiov1alpha3.StringMatch{
-				MatchType: &istiov1alpha3.StringMatch_Regex{
-					Regex: constants.PredictPrefix(),
-				},
-			},
 			Authority: &istiov1alpha3.StringMatch{
 				MatchType: &istiov1alpha3.StringMatch_Regex{
 					Regex: constants.HostRegExp(network.GetServiceHostname(serviceName, namespace)),
@@ -458,24 +448,6 @@ func TestCreateVirtualService(t *testing.T) {
 				Hosts:    []string{serviceHostName, serviceInternalHostName},
 				Gateways: []string{constants.KnativeIngressGateway, constants.KnativeLocalGateway},
 				Http: []*istiov1alpha3.HTTPRoute{
-					{
-						Match: predictorRouteMatch,
-						Route: []*istiov1alpha3.HTTPRouteDestination{
-							{
-								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost, Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort}},
-								Weight:      100,
-								Headers: &istiov1alpha3.Headers{
-									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
-										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), namespace)},
-									},
-								},
-							},
-						},
-						Retries: &istiov1alpha3.HTTPRetry{
-							Attempts:      3,
-							PerTryTimeout: RetryTimeout,
-						},
-					},
 					{
 						Match: []*istiov1alpha3.HTTPMatchRequest{
 							{
@@ -521,6 +493,24 @@ func TestCreateVirtualService(t *testing.T) {
 							PerTryTimeout: RetryTimeout,
 						},
 					},
+					{
+						Match: predictorRouteMatch,
+						Route: []*istiov1alpha3.HTTPRouteDestination{
+							{
+								Destination: &istiov1alpha3.Destination{Host: constants.LocalGatewayHost, Port: &istiov1alpha3.PortSelector{Number: constants.CommonDefaultHttpPort}},
+								Weight:      100,
+								Headers: &istiov1alpha3.Headers{
+									Request: &istiov1alpha3.Headers_HeaderOperations{Set: map[string]string{
+										"Host": network.GetServiceHostname(constants.DefaultPredictorServiceName(serviceName), namespace)},
+									},
+								},
+							},
+						},
+						Retries: &istiov1alpha3.HTTPRetry{
+							Attempts:      3,
+							PerTryTimeout: RetryTimeout,
+						},
+					},
 				},
 			},
 		},