This is an automated email from the ASF dual-hosted git repository.

kuanhsun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/submarine.git


The following commit(s) were added to refs/heads/master by this push:
     new c15baa7  SUBMARINE-1130. New route to serve pod
c15baa7 is described below

commit c15baa7fbe7bf314061559a8514be6220b66bb63
Author: jeff-901 <b07901...@ntu.edu.tw>
AuthorDate: Sun Dec 12 10:31:31 2021 +0800

    SUBMARINE-1130. New route to serve pod
    
    ### What is this PR for?
    Add a new route to serve pod.
    new route: http://\{submarine ip}/{model name}/{model 
version}/api/v1.0/predictions
    
    ### What type of PR is it?
    Feature
    
    ### Todos
    
    ### What is the Jira issue?
    https://issues.apache.org/jira/browse/SUBMARINE-1130
    
    ### How should this be tested?
    
    ### Screenshots (if appropriate)
    
    ### Questions:
    * Do the license files need updating? No
    * Are there breaking changes for older versions? No
    * Does this need new documentation? No
    
    Author: jeff-901 <b07901...@ntu.edu.tw>
    
    Signed-off-by: kuanhsun <kuanh...@apache.org>
    
    Closes #829 from jeff-901/SUBMARINE-1130 and squashes the following commits:
    
    2ea9c5a6 [jeff-901] create virtual service for serve pod
---
 .../artifacts/submarine/submarine-rbac.yaml        |  13 ++
 .../serve/istio/IstioHTTPDestination.java          |  54 ++++++++
 .../serve/istio/IstioHTTPMatchRequest.java         |  39 ++++++
 .../submarine/serve/istio/IstioHTTPRoute.java      |  67 +++++++++
 .../submarine/serve/istio/IstioVirtualService.java | 153 +++++++++++++++++++++
 .../submarine/serve/utils/IstioConstants.java      |  42 ++++++
 .../server/submitter/k8s/K8sSubmitter.java         |  43 +++++-
 7 files changed, 405 insertions(+), 6 deletions(-)

diff --git a/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml 
b/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
index f568dac..58d8264 100644
--- a/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
+++ b/submarine-cloud-v2/artifacts/submarine/submarine-rbac.yaml
@@ -68,6 +68,19 @@ rules:
   - patch
   - update
 - apiGroups:
+  - networking.istio.io
+  resources:
+  - virtualservices
+  verbs:
+  - get
+  - list
+  - watch
+  - create
+  - delete
+  - deletecollection
+  - patch
+  - update  
+- apiGroups:
   - ""
   resources:
   - pods
diff --git 
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPDestination.java
 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPDestination.java
new file mode 100644
index 0000000..fc375de
--- /dev/null
+++ 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPDestination.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+import org.apache.submarine.serve.utils.IstioConstants;
+
+public class IstioHTTPDestination {
+  @SerializedName("destination")
+  private IstioDestination destination;
+
+  public IstioHTTPDestination(String host){
+    this.destination = new IstioDestination(host);
+  }
+
+
+  public static class IstioDestination{
+    @SerializedName("host")
+    private String host;
+
+    @SerializedName("port")
+    private IstioPort port;
+
+    public IstioDestination(String host) {
+      this.host = host;
+      this.port = new IstioPort(IstioConstants.DEFAULT_SERVE_POD_PORT);
+    }
+  }
+
+  public static class IstioPort {
+    @SerializedName("number")
+    private Integer number;
+
+    public IstioPort(Integer port){
+      this.number = port;
+    }
+  }
+}
diff --git 
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPMatchRequest.java
 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPMatchRequest.java
new file mode 100644
index 0000000..18e0b6c
--- /dev/null
+++ 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPMatchRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+
+public class IstioHTTPMatchRequest {
+  @SerializedName("uri")
+  private IstioPrefix prefix;
+
+  public IstioHTTPMatchRequest(String prefix) {
+    this.prefix = new IstioPrefix(prefix);
+  }
+
+  public static class IstioPrefix {
+    @SerializedName("prefix")
+    private String path;
+
+    public IstioPrefix(String path){
+      this.path = path;
+    }
+  }
+}
diff --git 
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPRoute.java
 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPRoute.java
new file mode 100644
index 0000000..7f7ff9a
--- /dev/null
+++ 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioHTTPRoute.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+import org.apache.submarine.serve.utils.IstioConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IstioHTTPRoute {
+  @SerializedName("match")
+  private List<IstioHTTPMatchRequest> match = new ArrayList<>();
+
+  @SerializedName("route")
+  private List<IstioHTTPDestination> route = new ArrayList<>();
+
+  @SerializedName("rewrite")
+  private IstioRewrite rewrite;
+
+  public IstioHTTPRoute() {
+    this.rewrite = new IstioRewrite(IstioConstants.REWRITE_URL);
+  }
+
+  @Override
+  public String toString() {
+    return "'rewrite': {'uri': " + rewrite.getRewrite() + "}";
+
+  }
+
+  public void addHTTPMatchRequest(IstioHTTPMatchRequest match){
+    this.match.add(match);
+  }
+
+  public void addHTTPDestination(IstioHTTPDestination destination){
+    this.route.add(destination);
+  }
+  public static class IstioRewrite{
+    @SerializedName("uri")
+    private String uri;
+
+    public IstioRewrite(String rewrite){
+      this.uri = rewrite;
+    }
+
+    public String getRewrite() {
+      return uri;
+    }
+  }
+
+}
diff --git 
a/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioVirtualService.java
 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioVirtualService.java
new file mode 100644
index 0000000..dbe90de
--- /dev/null
+++ 
b/submarine-serve/src/main/java/org/apache/submarine/serve/istio/IstioVirtualService.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.istio;
+
+import com.google.gson.annotations.SerializedName;
+import io.kubernetes.client.models.V1ObjectMeta;
+import org.apache.submarine.serve.utils.IstioConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class IstioVirtualService {
+  @SerializedName("apiVersion")
+  private String apiVersion = IstioConstants.API_VERSION;
+
+  @SerializedName("kind")
+  private String kind = IstioConstants.KIND;
+
+  @SerializedName("metadata")
+  private V1ObjectMeta metadata;
+
+  @SerializedName("spec")
+  private IstioVirtualServiceSpec spec;
+
+  // transient to avoid being serialized
+  private transient String group = IstioConstants.GROUP;
+
+  private transient String version = IstioConstants.VERSION;
+
+  private transient String plural = IstioConstants.PLURAL;
+
+  public IstioVirtualService(String modelName, Integer modelVersion) {
+    V1ObjectMeta metadata = new V1ObjectMeta();
+    metadata.setName(modelName);
+    metadata.setNamespace(IstioConstants.DEFAULT_NAMESPACE);
+    setMetadata(metadata);
+    setSpec(new IstioVirtualServiceSpec(modelName, modelVersion));
+  }
+
+  public String getApiVersion() {
+    return apiVersion;
+  }
+
+  public void setApiVersion(String apiVersion) {
+    this.apiVersion = apiVersion;
+  }
+
+  public String getKind() {
+    return kind;
+  }
+
+  public void setKind(String kind) {
+    this.kind = kind;
+  }
+
+  public V1ObjectMeta getMetadata() {
+    return metadata;
+  }
+
+  public void setMetadata(V1ObjectMeta metadata) {
+    this.metadata = metadata;
+  }
+
+  public String getGroup() {
+    return group;
+  }
+
+  public void setGroup(String group) {
+    this.group = group;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(String version) {
+    this.version = version;
+  }
+
+  public String getPlural() {
+    return plural;
+  }
+
+  public void setPlural(String plural) {
+    this.plural = plural;
+  }
+
+  public IstioVirtualServiceSpec getSpec() {
+    return spec;
+  }
+
+  public void setSpec(IstioVirtualServiceSpec istioVirtualServiceSpec){
+    this.spec = istioVirtualServiceSpec;
+  }
+
+  public static class IstioVirtualServiceSpec {
+    @SerializedName("hosts")
+    private List<String> hosts = new ArrayList<>();
+    @SerializedName("gateways")
+    private List<String> gateways = new ArrayList<>();
+    @SerializedName("http")
+    private List<IstioHTTPRoute> httpRoute = new ArrayList<>();
+
+    public IstioVirtualServiceSpec(String modelName, Integer modelVersion) {
+      hosts.add(IstioConstants.DEFAULT_INGRESS_HOST);
+      gateways.add(IstioConstants.DEFAULT_GATEWAY);
+      IstioHTTPDestination destination = new IstioHTTPDestination(
+          modelName + "-" + IstioConstants.DEFAULT_NAMESPACE);
+      IstioHTTPMatchRequest matchRequest = new IstioHTTPMatchRequest("/" + 
modelName
+          + "/"  + String.valueOf(modelVersion) + "/");
+      IstioHTTPRoute httpRoute = new IstioHTTPRoute();
+      httpRoute.addHTTPDestination(destination);
+      httpRoute.addHTTPMatchRequest(matchRequest);
+      setHTTPRoute(httpRoute);
+    }
+
+    public List<String> getHosts() {
+      return this.hosts;
+    }
+
+    public void addHost(String host) {
+      hosts.add(host);
+    }
+
+    public List<String> getGateways() {
+      return this.gateways;
+    }
+
+    public void addGateway(String gateway) {
+      gateways.add(gateway);
+    }
+
+    public void setHTTPRoute(IstioHTTPRoute istioHTTPRoute){
+      this.httpRoute.add(istioHTTPRoute);
+    }
+  }
+}
diff --git 
a/submarine-serve/src/main/java/org/apache/submarine/serve/utils/IstioConstants.java
 
b/submarine-serve/src/main/java/org/apache/submarine/serve/utils/IstioConstants.java
new file mode 100644
index 0000000..10ae72d
--- /dev/null
+++ 
b/submarine-serve/src/main/java/org/apache/submarine/serve/utils/IstioConstants.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.submarine.serve.utils;
+
+public class IstioConstants {
+  public static final String API_VERSION = "networking.istio.io/v1beta1";
+
+  public static final String KIND = "VirtualService";
+
+  public static final String GROUP = "networking.istio.io";
+
+  public static final String VERSION = "v1beta1";
+
+  public static final String PLURAL = "virtualservices";
+
+  public static final String REWRITE_URL = "/"; 
+
+  public static final String DEFAULT_NAMESPACE = "default";
+
+  public static final String DEFAULT_GATEWAY = "istio-system/seldon-gateway";
+
+  public static final Integer DEFAULT_SERVE_POD_PORT = 8000;
+
+  public static final String DEFAULT_INGRESS_HOST = "*"; 
+
+}
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
index c1e8298..131e927 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/K8sSubmitter.java
@@ -57,6 +57,7 @@ import io.kubernetes.client.util.Watch;
 
 import org.apache.submarine.commons.utils.SubmarineConfiguration;
 import org.apache.submarine.commons.utils.exception.SubmarineRuntimeException;
+import org.apache.submarine.serve.istio.IstioVirtualService;
 import org.apache.submarine.serve.pytorch.SeldonPytorchServing;
 import org.apache.submarine.serve.seldon.SeldonDeployment;
 import org.apache.submarine.serve.tensorflow.SeldonTFServing;
@@ -117,7 +118,6 @@ public class K8sSubmitter implements Submitter {
   public void initialize(SubmarineConfiguration conf) {
     try {
       String path = System.getenv(KUBECONFIG_ENV);
-      //      path = System.getProperty("user.home") + "/.kube/config"; 
//TODO(tmp)
       KubeConfig config = KubeConfig.loadKubeConfig(new FileReader(path));
       client = ClientBuilder.kubeconfig(config).build();
     } catch (Exception e) {
@@ -522,16 +522,39 @@ public class K8sSubmitter implements Submitter {
   public void createServe(ServeSpec spec)
       throws SubmarineRuntimeException {
     SeldonDeployment seldonDeployment = parseServeSpec(spec);
-
+    IstioVirtualService istioVirtualService = new 
IstioVirtualService(spec.getModelName(),
+        spec.getModelVersion());
     try {
       api.createNamespacedCustomObject(seldonDeployment.getGroup(),
-              seldonDeployment.getVersion(),
+               seldonDeployment.getVersion(),
+               "default",
+               seldonDeployment.getPlural(),
+               seldonDeployment,
+               "true");
+    } catch (ApiException e) {
+      LOG.error(e.getMessage(), e);
+      throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
+    }
+    try {
+      api.createNamespacedCustomObject(istioVirtualService.getGroup(),
+              istioVirtualService.getVersion(),
               "default",
-              seldonDeployment.getPlural(),
-              seldonDeployment,
+              istioVirtualService.getPlural(),
+              istioVirtualService,
               "true");
     } catch (ApiException e) {
       LOG.error(e.getMessage(), e);
+      try {
+        api.deleteNamespacedCustomObject(seldonDeployment.getGroup(),
+              seldonDeployment.getVersion(),
+              "default",
+              seldonDeployment.getPlural(),
+              seldonDeployment.getMetadata().getName(),
+              new 
V1DeleteOptionsBuilder().withApiVersion(seldonDeployment.getApiVersion()).build(),
+              null, null, null);
+      } catch (ApiException e1) {
+        LOG.error(e1.getMessage(), e1);
+      }
       throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
     }
   }
@@ -540,7 +563,8 @@ public class K8sSubmitter implements Submitter {
   public void deleteServe(ServeSpec spec)
       throws SubmarineRuntimeException {
     SeldonDeployment seldonDeployment = parseServeSpec(spec);
-
+    IstioVirtualService istioVirtualService = new 
IstioVirtualService(spec.getModelName(),
+        spec.getModelVersion());
     try {
       api.deleteNamespacedCustomObject(seldonDeployment.getGroup(),
               seldonDeployment.getVersion(),
@@ -549,6 +573,13 @@ public class K8sSubmitter implements Submitter {
               seldonDeployment.getMetadata().getName(),
               new 
V1DeleteOptionsBuilder().withApiVersion(seldonDeployment.getApiVersion()).build(),
               null, null, null);
+      api.deleteNamespacedCustomObject(istioVirtualService.getGroup(),
+              istioVirtualService.getVersion(),
+              "default",
+              istioVirtualService.getPlural(),
+              istioVirtualService.getMetadata().getName(),
+              new 
V1DeleteOptionsBuilder().withApiVersion(istioVirtualService.getApiVersion()).build(),
+              null, null, null);
     } catch (ApiException e) {
       LOG.error(e.getMessage(), e);
       throw new SubmarineRuntimeException(e.getCode(), e.getMessage());

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@submarine.apache.org
For additional commands, e-mail: dev-h...@submarine.apache.org

Reply via email to