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]