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

liuxun 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 115b828  SUBMARINE-632. Users only get their own notebook instances
115b828 is described below

commit 115b82821c7d5166fe88b78dbcd6c37f6328d8bd
Author: Ryan Lo <[email protected]>
AuthorDate: Sat Sep 26 22:56:37 2020 +0800

    SUBMARINE-632. Users only get their own notebook instances
    
    ### What is this PR for?
    1. User can get themselves notebook instances with user id by labeling 
notebook pod.
    
    curl -X GET  http://SUBMARINE_IP:SUBMARINE_PORT/api/v1/notebook?id=USER_ID
    
    2. Update notebook RestAPI test
    
    ### What type of PR is it?
    [Improvement]
    
    ### Todos
    * [kobe860219] - Update the workbench with new notebookSpec to create/list 
user's notebook instances.
    
    ### What is the Jira issue?
    
[SUBMARINE-632](https://issues.apache.org/jira/projects/SUBMARINE/issues/SUBMARINE-632)
    
    ### How should this be tested?
    [travis CI](https://travis-ci.org/github/lowc1012/submarine/jobs/731864939)
    
    ### Screenshots (if appropriate)
    <img width="719" alt="image" 
src="https://user-images.githubusercontent.com/52355146/94802125-a8f11f00-0419-11eb-9e68-4520475b26fd.png";>
    
    <img width="782" alt="image2" 
src="https://user-images.githubusercontent.com/52355146/94801767-1cdef780-0419-11eb-8824-6782d2d36c7b.png";>
    
    ### Questions:
    * Does the licenses files need update? No
    * Is there breaking changes for older versions? No
    * Does this needs documentation? No
    
    Author: Ryan Lo <[email protected]>
    
    Closes #423 from lowc1012/SUBMARINE-632 and squashes the following commits:
    
    169a64e [Ryan Lo] SUBMARINE-632. Users only get their own notebook instances
---
 .../org/apache/submarine/server/api/Submitter.java | 10 +++
 .../submarine/server/api/spec/NotebookMeta.java    | 17 ++++
 .../submarine/server/notebook/NotebookManager.java | 19 +++++
 .../submarine/server/rest/NotebookRestApi.java     |  6 +-
 .../server/submitter/k8s/K8sSubmitter.java         | 93 ++++++++++++++++------
 .../server/submitter/k8s/model/NotebookCR.java     |  1 +
 .../server/submitter/k8s/model/NotebookCRList.java | 72 +++++++++++++++++
 .../server/submitter/k8s/model/NotebookCRSpec.java |  7 ++
 .../submitter/k8s/NotebookSpecParserTest.java      | 12 +++
 .../src/test/resources/notebook_req.json           |  3 +-
 .../apache/submarine/rest/NotebookRestApiIT.java   | 58 ++++++++++++++
 .../{notebook-req.json => notebook-req-2.json}     |  5 +-
 .../src/test/resources/notebook/notebook-req.json  |  3 +-
 .../src/test/resources/notebook/notebook-req.yaml  |  1 +
 14 files changed, 277 insertions(+), 30 deletions(-)

diff --git 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
index 8c7ea49..d3fd2e9 100644
--- 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
+++ 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/Submitter.java
@@ -27,6 +27,8 @@ import org.apache.submarine.server.api.notebook.Notebook;
 import org.apache.submarine.server.api.spec.ExperimentSpec;
 import org.apache.submarine.server.api.spec.NotebookSpec;
 
+import java.util.List;
+
 /**
  * The submitter should implement this interface.
  */
@@ -109,4 +111,12 @@ public interface Submitter {
    * @throws SubmarineRuntimeException running error
    */
   Notebook deleteNotebook(NotebookSpec spec) throws SubmarineRuntimeException;
+
+  /**
+   * List notebooks with userID
+   * @param id user ID
+   * @return object
+   * @throws SubmarineRuntimeException running error
+   */
+  List<Notebook> listNotebook(String id) throws SubmarineRuntimeException;
 }
diff --git 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/NotebookMeta.java
 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/NotebookMeta.java
index b8d314c..fc46a7f 100644
--- 
a/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/NotebookMeta.java
+++ 
b/submarine-server/server-api/src/main/java/org/apache/submarine/server/api/spec/NotebookMeta.java
@@ -22,6 +22,7 @@ package org.apache.submarine.server.api.spec;
 public class NotebookMeta {
   private String name;
   private String namespace;
+  private String ownerId;
 
   public NotebookMeta() {
 
@@ -58,4 +59,20 @@ public class NotebookMeta {
   public void setNamespace(String namespace) {
     this.namespace = namespace;
   }
+
+  /**
+   * Get the ownerId
+   * @return ownerId
+   */
+  public String getOwnerId() {
+    return ownerId;
+  }
+
+  /**
+   * Set the ownerId
+   * @param ownerId ownerId
+   */
+  public void setOwnerId(String ownerId) {
+    this.ownerId = ownerId;
+  }
 }
diff --git 
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
 
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
index bb932d0..92dbfed 100644
--- 
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
+++ 
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/notebook/NotebookManager.java
@@ -115,6 +115,25 @@ public class NotebookManager {
   }
 
   /**
+   * Get a list of notebook with user id
+   * @param id user id
+   * @return a list of notebook
+   */
+  public List<Notebook> listNotebooksByUserId(String id) {
+    List<Notebook> notebookList = submitter.listNotebook(id);
+    for (Notebook notebook : notebookList) {
+      for (Map.Entry<String, Notebook> entry : cachedNotebookMap.entrySet()) {
+        Notebook cachedNotebook = entry.getValue();
+        if (cachedNotebook.getUid().equals(notebook.getUid())) {
+          notebook.setNotebookId(cachedNotebook.getNotebookId());
+          notebook.setSpec(cachedNotebook.getSpec());
+        }
+      }
+    }
+    return notebookList;
+  }
+
+  /**
    * Get a notebook instance
    * @param id notebook id
    * @return object
diff --git 
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/NotebookRestApi.java
 
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/NotebookRestApi.java
index bfa4c91..3e0b38d 100644
--- 
a/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/NotebookRestApi.java
+++ 
b/submarine-server/server-core/src/main/java/org/apache/submarine/server/rest/NotebookRestApi.java
@@ -95,7 +95,7 @@ public class NotebookRestApi {
 
   /**
    * List all notebooks
-   * @param namespace namespace
+   * @param id user id
    * @return notebook list
    */
   @GET
@@ -105,9 +105,9 @@ public class NotebookRestApi {
           responses = {
                   @ApiResponse(description = "successful operation", content = 
@Content(
                           schema = @Schema(implementation = 
JsonResponse.class)))})
-  public Response listNotebooks(@QueryParam("namespace") String namespace) {
+  public Response listNotebooks(@QueryParam("id") String id) {
     try {
-      List<Notebook> notebookList = 
notebookManager.listNotebooksByNamespace(namespace);
+      List<Notebook> notebookList = notebookManager.listNotebooksByUserId(id);
       return new 
JsonResponse.Builder<List<Notebook>>(Response.Status.OK).success(true)
               .message("List all notebook 
instances").result(notebookList).build();
     } catch (SubmarineRuntimeException e) {
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 555e8bb..99402a9 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
@@ -22,9 +22,11 @@ package org.apache.submarine.server.submitter.k8s;
 import java.io.FileReader;
 import java.io.IOException;
 import java.text.SimpleDateFormat;
+import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -53,6 +55,7 @@ import org.apache.submarine.server.api.notebook.Notebook;
 import org.apache.submarine.server.api.spec.ExperimentMeta;
 import org.apache.submarine.server.api.spec.ExperimentSpec;
 import org.apache.submarine.server.api.spec.NotebookSpec;
+import org.apache.submarine.server.submitter.k8s.model.NotebookCRList;
 import 
org.apache.submarine.server.submitter.k8s.model.ingressroute.IngressRoute;
 import 
org.apache.submarine.server.submitter.k8s.model.ingressroute.IngressRouteSpec;
 import org.apache.submarine.server.submitter.k8s.model.NotebookCR;
@@ -117,7 +120,7 @@ public class K8sSubmitter implements Submitter {
       MLJob mlJob = ExperimentSpecParser.parseJob(spec);
       Object object = api.createNamespacedCustomObject(mlJob.getGroup(), 
mlJob.getVersion(),
           mlJob.getMetadata().getNamespace(), mlJob.getPlural(), mlJob, 
"true");
-      experiment = parseResponseObject(object, ParseOp.PARSE_OP_RESULT);
+      experiment = parseNotebookResponseObject(object, 
ParseOp.PARSE_OP_RESULT);
     } catch (InvalidSpecException e) {
       LOG.error("K8s submitter: parse Job object failed by " + e.getMessage(), 
e);
       throw new SubmarineRuntimeException(400, e.getMessage());
@@ -135,7 +138,7 @@ public class K8sSubmitter implements Submitter {
       MLJob mlJob = ExperimentSpecParser.parseJob(spec);
       Object object = api.getNamespacedCustomObject(mlJob.getGroup(), 
mlJob.getVersion(),
           mlJob.getMetadata().getNamespace(), mlJob.getPlural(), 
mlJob.getMetadata().getName());
-      experiment = parseResponseObject(object, ParseOp.PARSE_OP_RESULT);
+      experiment = parseNotebookResponseObject(object, 
ParseOp.PARSE_OP_RESULT);
     } catch (InvalidSpecException e) {
       throw new SubmarineRuntimeException(200, e.getMessage());
     } catch (ApiException e) {
@@ -152,7 +155,7 @@ public class K8sSubmitter implements Submitter {
       Object object = api.patchNamespacedCustomObject(mlJob.getGroup(), 
mlJob.getVersion(),
           mlJob.getMetadata().getNamespace(), mlJob.getPlural(), 
mlJob.getMetadata().getName(),
           mlJob);
-      experiment = parseResponseObject(object, ParseOp.PARSE_OP_RESULT);
+      experiment = parseNotebookResponseObject(object, 
ParseOp.PARSE_OP_RESULT);
     } catch (InvalidSpecException e) {
       throw new SubmarineRuntimeException(200, e.getMessage());
     } catch (ApiException e) {
@@ -169,7 +172,7 @@ public class K8sSubmitter implements Submitter {
       Object object = api.deleteNamespacedCustomObject(mlJob.getGroup(), 
mlJob.getVersion(),
           mlJob.getMetadata().getNamespace(), mlJob.getPlural(), 
mlJob.getMetadata().getName(),
           MLJobConverter.toDeleteOptionsFromMLJob(mlJob), null, null, null);
-      experiment = parseResponseObject(object, ParseOp.PARSE_OP_DELETE);
+      experiment = parseNotebookResponseObject(object, 
ParseOp.PARSE_OP_DELETE);
     } catch (InvalidSpecException e) {
       throw new SubmarineRuntimeException(200, e.getMessage());
     } catch (ApiException e) {
@@ -178,7 +181,7 @@ public class K8sSubmitter implements Submitter {
     return experiment;
   }
 
-  private Experiment parseResponseObject(Object object, ParseOp op) throws 
SubmarineRuntimeException {
+  private Experiment parseNotebookResponseObject(Object object, ParseOp op) 
throws SubmarineRuntimeException {
     Gson gson = new JSON().getGson();
     String jsonString = gson.toJson(object);
     LOG.info("Upstream response JSON: {}", jsonString);
@@ -249,9 +252,12 @@ public class K8sSubmitter implements Submitter {
     try {
       // create notebook custom resource
       NotebookCR notebookCR = NotebookSpecParser.parseNotebook(spec);
+      Map<String, String> labels = new HashMap<>();
+      labels.put(NotebookCR.NOTEBOOK_OWNER_SELECTOR_KET, 
spec.getMeta().getOwnerId());
+      notebookCR.getMetadata().setLabels(labels);
       Object object = api.createNamespacedCustomObject(notebookCR.getGroup(), 
notebookCR.getVersion(),
               notebookCR.getMetadata().getNamespace(), notebookCR.getPlural(), 
notebookCR, "true");
-      notebook = parseResponseObject(object);
+      notebook = parseNotebookResponseObject(object);
 
       // create Traefik custom resource
       createIngressRoute(notebookCR.getMetadata().getNamespace(), 
notebookCR.getMetadata().getName());
@@ -274,7 +280,7 @@ public class K8sSubmitter implements Submitter {
       Object object = api.getNamespacedCustomObject(notebookCR.getGroup(), 
notebookCR.getVersion(),
               notebookCR.getMetadata().getNamespace(),
               notebookCR.getPlural(), notebookCR.getMetadata().getName());
-      notebook = parseResponseObject(object);
+      notebook = parseNotebookResponseObject(object);
     } catch (ApiException e) {
       throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
     }
@@ -291,7 +297,7 @@ public class K8sSubmitter implements Submitter {
               notebookCR.getMetadata().getName(),
               new 
V1DeleteOptionsBuilder().withApiVersion(notebookCR.getApiVersion()).build(),
               null, null, null);
-      notebook = parseResponseObject(object);
+      notebook = parseNotebookResponseObject(object);
       deleteIngressRoute(notebookCR.getMetadata().getNamespace(), 
notebookCR.getMetadata().getName());
     } catch (ApiException e) {
       throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
@@ -299,27 +305,33 @@ public class K8sSubmitter implements Submitter {
     return notebook;
   }
 
-  private Notebook parseResponseObject(Object obj) throws 
SubmarineRuntimeException {
+  @Override
+  public List<Notebook> listNotebook(String id) throws 
SubmarineRuntimeException {
+    List<Notebook> notebookList;
+    try {
+      Object object = 
api.listClusterCustomObject(NotebookCR.CRD_NOTEBOOK_GROUP_V1,
+              NotebookCR.CRD_NOTEBOOK_VERSION_V1, 
NotebookCR.CRD_NOTEBOOK_PLURAL_V1,
+              "true", null, NotebookCR.NOTEBOOK_OWNER_SELECTOR_KET + "=" + id,
+              null, null, null);
+      notebookList = parseNotebookListResponseObject(object);
+    } catch (ApiException e) {
+      throw new SubmarineRuntimeException(e.getCode(), e.getMessage());
+    }
+    return notebookList;
+  }
+
+  private Notebook parseNotebookResponseObject(Object obj) throws 
SubmarineRuntimeException {
     Gson gson = new JSON().getGson();
     String jsonString = gson.toJson(obj);
     LOG.info("Upstream response JSON: {}", jsonString);
     Notebook notebook;
     try {
-      notebook = new Notebook();
       NotebookCR notebookCR = gson.fromJson(jsonString, NotebookCR.class);
-      notebook.setUid(notebookCR.getMetadata().getUid());
-      notebook.setName(notebookCR.getMetadata().getName());
-      // notebook url
-      notebook.setUrl("/notebook/" + notebookCR.getMetadata().getNamespace() + 
"/" +
-              notebookCR.getMetadata().getName() + "/");
-      DateTime createdTime = notebookCR.getMetadata().getCreationTimestamp();
-      if (createdTime != null) {
-        notebook.setCreatedTime(createdTime.toString());
-        notebook.setStatus(Notebook.Status.STATUS_CREATED.getValue());
-      }
-
-      // deleted notebook
-      if (notebookCR.getMetadata().getName() == null) {
+      if (notebookCR.getMetadata().getName() != null) {
+        notebook = buildNotebookResponse(notebookCR);
+        // notebook is deleted
+      } else {
+        notebook = new Notebook();
         SimpleDateFormat dateFormat = new 
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
         Date current = new Date();
         notebook.setDeletedTime(dateFormat.format(current));
@@ -333,6 +345,41 @@ public class K8sSubmitter implements Submitter {
     return notebook;
   }
 
+  private List<Notebook> parseNotebookListResponseObject(Object object) {
+    Gson gson = new JSON().getGson();
+    String jsonString = gson.toJson(object);
+    LOG.info("Upstream response JSON: {}", jsonString);
+
+    Notebook notebook;
+    List<Notebook> notebookList = new ArrayList<>();
+    try {
+      NotebookCRList notebookCRList = gson.fromJson(jsonString, 
NotebookCRList.class);
+      for (NotebookCR notebookCR : notebookCRList.getItems()) {
+        notebook = buildNotebookResponse(notebookCR);
+        notebookList.add(notebook);
+      }
+    } catch (JsonSyntaxException e) {
+      LOG.error("K8s submitter: parse response object failed by " + 
e.getMessage(), e);
+      throw new SubmarineRuntimeException(500, "K8s Submitter parse upstream 
response failed.");
+    }
+    return notebookList;
+  }
+
+  private Notebook buildNotebookResponse(NotebookCR notebookCR) {
+    Notebook notebook = new Notebook();
+    notebook.setUid(notebookCR.getMetadata().getUid());
+    notebook.setName(notebookCR.getMetadata().getName());
+    // notebook url
+    notebook.setUrl("/notebook/" + notebookCR.getMetadata().getNamespace() + 
"/" +
+            notebookCR.getMetadata().getName() + "/");
+    DateTime createdTime = notebookCR.getMetadata().getCreationTimestamp();
+    if (createdTime != null) {
+      notebook.setCreatedTime(createdTime.toString());
+      notebook.setStatus(Notebook.Status.STATUS_CREATED.getValue());
+    }
+    return notebook;
+  }
+
   private String getJobLabelSelector(ExperimentSpec experimentSpec) {
     // TODO(JohnTing): SELECTOR_KEY should be obtained from individual models 
in MLJOB
     if (experimentSpec.getMeta().getFramework()
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCR.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCR.java
index 96295d0..69d9fcc 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCR.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCR.java
@@ -29,6 +29,7 @@ public class NotebookCR {
   public static final String CRD_APIVERSION_V1 = CRD_NOTEBOOK_GROUP_V1 + "/" + 
CRD_NOTEBOOK_VERSION_V1;
   public static final String CRD_NOTEBOOK_KIND_V1 = "Notebook";
   public static final String CRD_NOTEBOOK_PLURAL_V1 = "notebooks";
+  public static final String NOTEBOOK_OWNER_SELECTOR_KET = "notebook-owner-id";
 
   @SerializedName("apiVersion")
   private String apiVersion;
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRList.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRList.java
new file mode 100644
index 0000000..0fa78b2
--- /dev/null
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRList.java
@@ -0,0 +1,72 @@
+/*
+ * 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.server.submitter.k8s.model;
+
+import com.google.gson.annotations.SerializedName;
+import io.kubernetes.client.models.V1ListMeta;
+
+import java.util.List;
+
+public class NotebookCRList {
+
+  @SerializedName("apiVersion")
+  private String apiVersion;
+
+  @SerializedName("items")
+  private List<NotebookCR> items;
+
+  @SerializedName("kind")
+  private String kind;
+
+  @SerializedName("metadata")
+  private V1ListMeta metadata;
+
+  public String getApiVersion() {
+    return apiVersion;
+  }
+
+  public void setApiVersion(String apiVersion) {
+    this.apiVersion = apiVersion;
+  }
+
+  public List<NotebookCR> getItems() {
+    return items;
+  }
+
+  public void setItems(List<NotebookCR> items) {
+    this.items = items;
+  }
+
+  public String getKind() {
+    return kind;
+  }
+
+  public void setKing(String kind) {
+    this.kind = kind;
+  }
+
+  public V1ListMeta getMetadata() {
+    return metadata;
+  }
+
+  public void setMetadata(V1ListMeta metadata) {
+    this.metadata = metadata;
+  }
+}
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRSpec.java
 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRSpec.java
index 05eb1dd..bd5b115 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRSpec.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/main/java/org/apache/submarine/server/submitter/k8s/model/NotebookCRSpec.java
@@ -20,9 +20,11 @@
 package org.apache.submarine.server.submitter.k8s.model;
 
 import com.google.gson.annotations.SerializedName;
+import io.kubernetes.client.models.V1EnvVar;
 import io.kubernetes.client.models.V1PodTemplateSpec;
 
 import java.math.BigDecimal;
+import java.util.List;
 
 public class NotebookCRSpec {
 
@@ -89,4 +91,9 @@ public class NotebookCRSpec {
     V1PodTemplateSpec podSpec = getTemplate();
     return podSpec.getSpec().getContainers().get(0).getImage();
   }
+
+  public List<V1EnvVar> getEnvs() {
+    V1PodTemplateSpec podSpec = getTemplate();
+    return podSpec.getSpec().getContainers().get(0).getEnv();
+  }
 }
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/test/java/org/apache/submarine/server/submitter/k8s/NotebookSpecParserTest.java
 
b/submarine-server/server-submitter/submitter-k8s/src/test/java/org/apache/submarine/server/submitter/k8s/NotebookSpecParserTest.java
index 05de939..e982a25 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/test/java/org/apache/submarine/server/submitter/k8s/NotebookSpecParserTest.java
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/test/java/org/apache/submarine/server/submitter/k8s/NotebookSpecParserTest.java
@@ -19,6 +19,7 @@
 
 package org.apache.submarine.server.submitter.k8s;
 
+import io.kubernetes.client.models.V1EnvVar;
 import io.kubernetes.client.models.V1ObjectMeta;
 import org.apache.submarine.server.api.spec.NotebookMeta;
 import org.apache.submarine.server.api.spec.NotebookPodSpec;
@@ -31,6 +32,7 @@ import org.junit.Test;
 
 import java.io.IOException;
 import java.net.URISyntaxException;
+import java.util.Map;
 
 public class NotebookSpecParserTest extends SpecBuilder {
 
@@ -47,6 +49,8 @@ public class NotebookSpecParserTest extends SpecBuilder {
   private void validateMetadata(NotebookMeta meta, V1ObjectMeta actualMeta) {
     Assert.assertEquals(meta.getName(), actualMeta.getName());
     Assert.assertEquals(meta.getNamespace(), actualMeta.getNamespace());
+    Assert.assertEquals(meta.getOwnerId(),
+            
actualMeta.getLabels().get(NotebookCR.NOTEBOOK_OWNER_SELECTOR_KET));
   }
 
   private void validateEnvironment(NotebookSpec spec, NotebookCRSpec 
actualPodSpec) {
@@ -62,6 +66,14 @@ public class NotebookSpecParserTest extends SpecBuilder {
     }
     Assert.assertNotNull(notebookCRSpec);
 
+    // environment variable
+    for (Map.Entry<String, String> entry : podSpec.getEnvVars().entrySet()) {
+      V1EnvVar env = new V1EnvVar();
+      env.setName(entry.getKey());
+      env.setValue(env.getValue());
+      Assert.assertTrue(notebook.getSpec().getEnvs().contains(env));
+    }
+
     // mem
     String expectedContainerMem = podSpec.getMemory();
     String actualContainerMem = notebookCRSpec.getContainerMemory();
diff --git 
a/submarine-server/server-submitter/submitter-k8s/src/test/resources/notebook_req.json
 
b/submarine-server/server-submitter/submitter-k8s/src/test/resources/notebook_req.json
index e46aec0..9c340c5 100644
--- 
a/submarine-server/server-submitter/submitter-k8s/src/test/resources/notebook_req.json
+++ 
b/submarine-server/server-submitter/submitter-k8s/src/test/resources/notebook_req.json
@@ -1,7 +1,8 @@
 {
   "meta": {
     "name": "my-nb",
-    "namespace": "default"
+    "namespace": "default",
+    "ownerId": "e9ca23d68d884d4ebb19d07889727dae"
   },
   "environment": {
     "name": "my-submarine-env"
diff --git 
a/submarine-test/test-k8s/src/test/java/org/apache/submarine/rest/NotebookRestApiIT.java
 
b/submarine-test/test-k8s/src/test/java/org/apache/submarine/rest/NotebookRestApiIT.java
index 8fd2bb5..4351bac 100644
--- 
a/submarine-test/test-k8s/src/test/java/org/apache/submarine/rest/NotebookRestApiIT.java
+++ 
b/submarine-test/test-k8s/src/test/java/org/apache/submarine/rest/NotebookRestApiIT.java
@@ -22,6 +22,7 @@ package org.apache.submarine.rest;
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
 import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
 import io.kubernetes.client.ApiClient;
 import io.kubernetes.client.ApiException;
@@ -165,6 +166,63 @@ public class NotebookRestApiIT extends 
AbstractSubmarineServerTest {
     Assert.assertEquals(Response.Status.OK.getStatusCode(), 
jsonResponse.getCode());
   }
 
+  @Test
+  public void testListNotebooksWithUserId() throws Exception {
+    // create environment
+    String envBody = loadContent("environment/test_env_3.json");
+    run(envBody, "application/json");
+    Gson gson = new GsonBuilder()
+            .registerTypeAdapter(EnvironmentId.class, new 
EnvironmentIdSerializer())
+            .registerTypeAdapter(EnvironmentId.class, new 
EnvironmentIdDeserializer())
+            .create();
+    GetMethod getMethod = httpGet(ENV_PATH + "/" + ENV_NAME);
+    Assert.assertEquals(Response.Status.OK.getStatusCode(),
+            getMethod.getStatusCode());
+
+    String json = getMethod.getResponseBodyAsString();
+    JsonResponse jsonResponse = gson.fromJson(json, JsonResponse.class);
+    Assert.assertEquals(Response.Status.OK.getStatusCode(),
+            jsonResponse.getCode());
+
+    Environment getEnvironment =
+            gson.fromJson(gson.toJson(jsonResponse.getResult()), 
Environment.class);
+    Assert.assertEquals(ENV_NAME, 
getEnvironment.getEnvironmentSpec().getName());
+
+    // create notebook instances
+    LOG.info("Create notebook servers by Notebook REST API");
+    String body = loadContent("notebook/notebook-req.json");
+    PostMethod postMethod = httpPost(BASE_API_PATH, body,"application/json");
+    Assert.assertEquals(Response.Status.OK.getStatusCode(), 
postMethod.getStatusCode());
+
+    body = loadContent("notebook/notebook-req-2.json");
+    postMethod = httpPost(BASE_API_PATH, body,"application/json");
+    Assert.assertEquals(Response.Status.OK.getStatusCode(), 
postMethod.getStatusCode());
+
+    // Get a list of notebook with user id
+    GetMethod getNotebookList = httpGet(BASE_API_PATH + 
"?id=e9ca23d68d884d4ebb19d07889727dae");
+    Assert.assertEquals(Response.Status.OK.getStatusCode(), 
getNotebookList.getStatusCode());
+
+    String jsonString = getNotebookList.getResponseBodyAsString();
+    JsonResponse notebookListJsonResponse = gson.fromJson(jsonString, 
JsonResponse.class);
+    Assert.assertEquals(Response.Status.OK.getStatusCode(), 
notebookListJsonResponse.getCode());
+
+    LOG.info("List notebooks: {}", jsonString);
+    JsonArray jsonArray = 
gson.fromJson(gson.toJson(notebookListJsonResponse.getResult()), 
JsonArray.class);
+    Assert.assertEquals(2, jsonArray.size());
+
+    // delete notebook instances
+    DeleteMethod deleteMethod;
+    for(JsonElement jsonElement : jsonArray) {
+      String notebookId = 
jsonElement.getAsJsonObject().get("notebookId").getAsString();
+      LOG.info("Delete notebook: {}", notebookId);
+      deleteMethod = httpDelete(BASE_API_PATH + "/" + notebookId);
+      Assert.assertEquals(Response.Status.OK.getStatusCode(), 
deleteMethod.getStatusCode());
+    }
+
+    // delete environment
+    deleteEnvironment();
+  }
+
   private void runTest(String body, String contentType) throws Exception {
     // create
     LOG.info("Create a notebook server by Notebook REST API");
diff --git 
a/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json 
b/submarine-test/test-k8s/src/test/resources/notebook/notebook-req-2.json
similarity index 63%
copy from submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json
copy to submarine-test/test-k8s/src/test/resources/notebook/notebook-req-2.json
index 0b95433..d3b45c7 100644
--- a/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json
+++ b/submarine-test/test-k8s/src/test/resources/notebook/notebook-req-2.json
@@ -1,7 +1,8 @@
 {
   "meta": {
-    "name": "test-nb",
-    "namespace": "default"
+    "name": "test-nb-2",
+    "namespace": "default",
+    "ownerId": "e9ca23d68d884d4ebb19d07889727dae"
   },
   "environment": {
     "name": "my-submarine-env"
diff --git 
a/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json 
b/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json
index 0b95433..ac5730a 100644
--- a/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json
+++ b/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.json
@@ -1,7 +1,8 @@
 {
   "meta": {
     "name": "test-nb",
-    "namespace": "default"
+    "namespace": "default",
+    "ownerId": "e9ca23d68d884d4ebb19d07889727dae"
   },
   "environment": {
     "name": "my-submarine-env"
diff --git 
a/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.yaml 
b/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.yaml
index 824c32e..9c39d48 100644
--- a/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.yaml
+++ b/submarine-test/test-k8s/src/test/resources/notebook/notebook-req.yaml
@@ -2,6 +2,7 @@
 meta:
   name: test-nb
   namespace: default
+  ownerId: e9ca23d68d884d4ebb19d07889727dae
 environment:
   name: my-submarine-env
 spec:


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to