diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterGroup.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterGroup.java index ee53f8e7571..f3b158c26a6 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterGroup.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/InterpreterGroup.java @@ -33,7 +33,7 @@ * and InterpreterGroup will have reference to these all interpreters. * * Remember, list of interpreters are dedicated to a note. - * (when InterpreterOption.perNoteSession==true) + * (when InterpreterOption.session==true) * So InterpreterGroup internally manages map of [noteId, list of interpreters] * * A InterpreterGroup runs on interpreter process. @@ -203,6 +203,14 @@ public void destroy(String noteId) { LOGGER.info("Destroy interpreter group " + getId() + " for note " + noteId); List intpForNote = this.get(noteId); destroy(intpForNote); + + if (remoteInterpreterProcess != null) { + remoteInterpreterProcess.dereference(); + if (remoteInterpreterProcess.referenceCount() <= 0) { + remoteInterpreterProcess = null; + allInterpreterGroups.remove(id); + } + } } @@ -222,6 +230,7 @@ public void destroy() { while (remoteInterpreterProcess.referenceCount() > 0) { remoteInterpreterProcess.dereference(); } + remoteInterpreterProcess = null; } allInterpreterGroups.remove(id); diff --git a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java index 073b84bbda2..e0cdaa338b1 100644 --- a/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java +++ b/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java @@ -298,6 +298,7 @@ public InterpreterResult interpret(String st, InterpreterContext context) { if (logger.isDebugEnabled()) { logger.debug("st:\n{}", st); } + FormType form = getFormType(); RemoteInterpreterProcess interpreterProcess = getInterpreterProcess(); Client client = null; diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java index b83a8891d0b..d9af812f164 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/rest/NotebookRestApi.java @@ -177,7 +177,7 @@ public Response putNotePermissions(@PathParam("noteId") String noteId, String re public Response bind(@PathParam("noteId") String noteId, String req) throws IOException { List settingIdList = gson.fromJson(req, new TypeToken>() { }.getType()); - notebook.bindInterpretersToNote(noteId, settingIdList); + notebook.bindInterpretersToNote(SecurityUtils.getPrincipal(), noteId, settingIdList); return new JsonResponse<>(Status.OK).build(); } @@ -458,7 +458,7 @@ public Response deleteParagraph(@PathParam("notebookId") String notebookId, } AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); - note.removeParagraph(paragraphId); + note.removeParagraph(SecurityUtils.getPrincipal(), paragraphId); note.persist(subject); notebookServer.broadcastNote(note); @@ -599,6 +599,11 @@ public Response runParagraph(@PathParam("notebookId") String notebookId, // handle params if presented handleParagraphParams(message, note, paragraph); + AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); + + paragraph.setAuthenticationInfo(subject); + note.persist(subject); + note.run(paragraph.getId()); return new JsonResponse<>(Status.OK).build(); } diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java index c6202355c83..de02fe0f3c8 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/server/ZeppelinServer.java @@ -89,7 +89,7 @@ public ZeppelinServer() throws Exception { this.heliumApplicationFactory = new HeliumApplicationFactory(); this.schedulerFactory = new SchedulerFactory(); this.replFactory = new InterpreterFactory(conf, notebookWsServer, - notebookWsServer, heliumApplicationFactory, depResolver); + notebookWsServer, heliumApplicationFactory, depResolver, SecurityUtils.isAuthenticated()); this.notebookRepo = new NotebookRepoSync(conf); this.notebookIndex = new LuceneSearch(); this.notebookAuthorization = NotebookAuthorization.init(conf); diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java index 2eee99e1e4f..969bdf9510d 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java @@ -134,7 +134,7 @@ public void onMessage(NotebookSocket conn, String msg) { if (LOG.isTraceEnabled()) { LOG.trace("RECEIVE MSG = " + messagereceived); } - + String ticket = TicketContainer.instance.getTicket(messagereceived.principal); if (ticket != null && !ticket.equals(messagereceived.ticket)){ /* not to pollute logs, log instead of exception */ @@ -472,7 +472,8 @@ public void saveInterpreterBindings(NotebookSocket conn, Message fromMessage) { List settingIdList = gson.fromJson(String.valueOf( fromMessage.data.get("selectedSettingIds")), new TypeToken>() { }.getType()); - notebook().bindInterpretersToNote(noteId, settingIdList); + AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal); + notebook().bindInterpretersToNote(subject.getUser(), noteId, settingIdList); broadcastInterpreterBindings(noteId, InterpreterBindingUtils.getInterpreterBindings(notebook(), noteId)); } catch (Exception e) { @@ -600,6 +601,8 @@ private void sendNote(NotebookSocket conn, HashSet userAndRoles, Noteboo return; } + String user = fromMessage.principal; + Note note = notebook.getNote(noteId); NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); if (note != null) { @@ -610,7 +613,7 @@ private void sendNote(NotebookSocket conn, HashSet userAndRoles, Noteboo } addConnectionToNote(note.getId(), conn); conn.send(serializeMessage(new Message(OP.NOTE).put("note", note))); - sendAllAngularObjects(note, conn); + sendAllAngularObjects(note, user, conn); } else { conn.send(serializeMessage(new Message(OP.NOTE).put("note", null))); } @@ -619,6 +622,7 @@ private void sendNote(NotebookSocket conn, HashSet userAndRoles, Noteboo private void sendHomeNote(NotebookSocket conn, HashSet userAndRoles, Notebook notebook, Message fromMessage) throws IOException { String noteId = notebook.getConf().getString(ConfVars.ZEPPELIN_NOTEBOOK_HOMESCREEN); + String user = fromMessage.principal; Note note = null; if (noteId != null) { @@ -634,7 +638,7 @@ private void sendHomeNote(NotebookSocket conn, HashSet userAndRoles, } addConnectionToNote(note.getId(), conn); conn.send(serializeMessage(new Message(OP.NOTE).put("note", note))); - sendAllAngularObjects(note, conn); + sendAllAngularObjects(note, user, conn); } else { removeConnectionFromAllNote(conn); conn.send(serializeMessage(new Message(OP.NOTE).put("note", null))); @@ -786,6 +790,8 @@ protected Note importNote(NotebookSocket conn, HashSet userAndRoles, AuthenticationInfo subject = null; if (fromMessage.principal != null) { subject = new AuthenticationInfo(fromMessage.principal); + } else { + subject = new AuthenticationInfo("anonymous"); } note = notebook.importNote(noteJson, noteName, subject); note.persist(subject); @@ -804,7 +810,7 @@ private void removeParagraph(NotebookSocket conn, HashSet userAndRoles, String noteId = getOpenNoteId(conn); final Note note = notebook.getNote(noteId); NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); - AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); + AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal); if (!notebookAuthorization.isWriter(noteId, userAndRoles)) { permissionError(conn, "write", fromMessage.principal, userAndRoles, notebookAuthorization.getWriters(noteId)); @@ -813,7 +819,7 @@ private void removeParagraph(NotebookSocket conn, HashSet userAndRoles, /** We dont want to remove the last paragraph */ if (!note.isLastParagraph(paragraphId)) { - note.removeParagraph(paragraphId); + note.removeParagraph(subject.getUser(), paragraphId); note.persist(subject); broadcastNote(note); } @@ -869,6 +875,7 @@ private void angularObjectUpdated(NotebookSocket conn, HashSet userAndRo String interpreterGroupId = (String) fromMessage.get("interpreterGroupId"); String varName = (String) fromMessage.get("name"); Object varValue = fromMessage.get("value"); + String user = fromMessage.principal; AngularObject ao = null; boolean global = false; // propagate change to (Remote) AngularObjectRegistry @@ -877,12 +884,12 @@ private void angularObjectUpdated(NotebookSocket conn, HashSet userAndRo List settings = notebook.getInterpreterFactory() .getInterpreterSettings(note.getId()); for (InterpreterSetting setting : settings) { - if (setting.getInterpreterGroup(note.getId()) == null) { + if (setting.getInterpreterGroup(user, note.getId()) == null) { continue; } - if (interpreterGroupId.equals(setting.getInterpreterGroup(note.getId()).getId())) { + if (interpreterGroupId.equals(setting.getInterpreterGroup(user, note.getId()).getId())) { AngularObjectRegistry angularObjectRegistry = setting - .getInterpreterGroup(note.getId()).getAngularObjectRegistry(); + .getInterpreterGroup(user, note.getId()).getAngularObjectRegistry(); // first trying to get local registry ao = angularObjectRegistry.get(varName, noteId, paragraphId); @@ -919,12 +926,12 @@ private void angularObjectUpdated(NotebookSocket conn, HashSet userAndRo List settings = notebook.getInterpreterFactory() .getInterpreterSettings(note.getId()); for (InterpreterSetting setting : settings) { - if (setting.getInterpreterGroup(n.getId()) == null) { + if (setting.getInterpreterGroup(user, n.getId()) == null) { continue; } - if (interpreterGroupId.equals(setting.getInterpreterGroup(n.getId()).getId())) { + if (interpreterGroupId.equals(setting.getInterpreterGroup(user, n.getId()).getId())) { AngularObjectRegistry angularObjectRegistry = setting - .getInterpreterGroup(n.getId()).getAngularObjectRegistry(); + .getInterpreterGroup(user, n.getId()).getAngularObjectRegistry(); this.broadcastExcept( n.getId(), new Message(OP.ANGULAR_OBJECT_UPDATE).put("angularObject", ao) @@ -1110,7 +1117,7 @@ private void moveParagraph(NotebookSocket conn, HashSet userAndRoles, No String noteId = getOpenNoteId(conn); final Note note = notebook.getNote(noteId); NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); - AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); + AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal); if (!notebookAuthorization.isWriter(noteId, userAndRoles)) { permissionError(conn, "write", fromMessage.principal, userAndRoles, notebookAuthorization.getWriters(noteId)); @@ -1129,7 +1136,7 @@ private void insertParagraph(NotebookSocket conn, HashSet userAndRoles, String noteId = getOpenNoteId(conn); final Note note = notebook.getNote(noteId); NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); - AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal()); + AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal); if (!notebookAuthorization.isWriter(noteId, userAndRoles)) { permissionError(conn, "write", fromMessage.principal, userAndRoles, notebookAuthorization.getWriters(noteId)); @@ -1181,14 +1188,9 @@ private void runParagraph(NotebookSocket conn, HashSet userAndRoles, Not String text = (String) fromMessage.get("paragraph"); p.setText(text); p.setTitle((String) fromMessage.get("title")); - if (!fromMessage.principal.equals("anonymous")) { - AuthenticationInfo authenticationInfo = new AuthenticationInfo(fromMessage.principal, - fromMessage.ticket); - p.setAuthenticationInfo(authenticationInfo); - - } else { - p.setAuthenticationInfo(new AuthenticationInfo()); - } + AuthenticationInfo authenticationInfo = + new AuthenticationInfo(fromMessage.principal, fromMessage.ticket); + p.setAuthenticationInfo(authenticationInfo); Map params = (Map) fromMessage .get("params"); @@ -1513,7 +1515,7 @@ public void afterStatusChange(Job job, Status before, Status after) { LOG.info("Job {} is finished", job.getId()); try { //TODO(khalid): may change interface for JobListener and pass subject from interpreter - note.persist(null); + note.persist(job instanceof Paragraph ? ((Paragraph) job).getAuthenticationInfo() : null); } catch (IOException e) { LOG.error(e.toString(), e); } @@ -1569,7 +1571,8 @@ public NotebookEventListener getNotebookInformationListener() { return new NotebookInformationListener(this); } - private void sendAllAngularObjects(Note note, NotebookSocket conn) throws IOException { + private void sendAllAngularObjects(Note note, String user, NotebookSocket conn) + throws IOException { List settings = notebook().getInterpreterFactory().getInterpreterSettings(note.getId()); if (settings == null || settings.size() == 0) { @@ -1577,17 +1580,15 @@ private void sendAllAngularObjects(Note note, NotebookSocket conn) throws IOExce } for (InterpreterSetting intpSetting : settings) { - AngularObjectRegistry registry = intpSetting.getInterpreterGroup(note.getId()) - .getAngularObjectRegistry(); + AngularObjectRegistry registry = + intpSetting.getInterpreterGroup(user, note.getId()).getAngularObjectRegistry(); List objects = registry.getAllWithGlobal(note.getId()); for (AngularObject object : objects) { - conn.send(serializeMessage(new Message(OP.ANGULAR_OBJECT_UPDATE) - .put("angularObject", object) - .put("interpreterGroupId", - intpSetting.getInterpreterGroup(note.getId()).getId()) - .put("noteId", note.getId()) - .put("paragraphId", object.getParagraphId()) - )); + conn.send(serializeMessage( + new Message(OP.ANGULAR_OBJECT_UPDATE).put("angularObject", object) + .put("interpreterGroupId", + intpSetting.getInterpreterGroup(user, note.getId()).getId()) + .put("noteId", note.getId()).put("paragraphId", object.getParagraphId()))); } } } @@ -1654,9 +1655,10 @@ private void getEditorSetting(NotebookSocket conn, Message fromMessage) String paragraphId = (String) fromMessage.get("paragraphId"); String replName = (String) fromMessage.get("magic"); String noteId = getOpenNoteId(conn); + String user = fromMessage.principal; Message resp = new Message(OP.EDITOR_SETTING); resp.put("paragraphId", paragraphId); - resp.put("editor", notebook().getInterpreterFactory().getEditorSetting(noteId, replName)); + resp.put("editor", notebook().getInterpreterFactory().getEditorSetting(user, noteId, replName)); conn.send(serializeMessage(resp)); return; } diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/SecurityUtils.java b/zeppelin-server/src/main/java/org/apache/zeppelin/utils/SecurityUtils.java index f9e5929a882..d81d2e6150b 100644 --- a/zeppelin-server/src/main/java/org/apache/zeppelin/utils/SecurityUtils.java +++ b/zeppelin-server/src/main/java/org/apache/zeppelin/utils/SecurityUtils.java @@ -119,4 +119,10 @@ public static HashSet getRoles() { return roles; } + /** + * Checked if shiro enabled or not + */ + public static boolean isAuthenticated() { + return org.apache.shiro.SecurityUtils.getSubject().isAuthenticated(); + } } diff --git a/zeppelin-server/src/main/resources/log4j.properties b/zeppelin-server/src/main/resources/log4j.properties new file mode 100644 index 00000000000..2f644074c89 --- /dev/null +++ b/zeppelin-server/src/main/resources/log4j.properties @@ -0,0 +1,25 @@ +# +# 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. +# + +log4j.rootLogger = INFO, stdout + +log4j.appender.stdout = org.apache.log4j.ConsoleAppender +log4j.appender.stdout.layout = org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%5p [%d] ({%t} %F[%M]:%L) - %m%n + +log4j.additivity.org.apache.zeppelin.interpreter = false +log4j.logger.org.apache.zeppelin.interpreter = DEBUG, stdout diff --git a/zeppelin-server/src/main/resources/shiro.ini b/zeppelin-server/src/main/resources/shiro.ini index 371a44e11e1..050c9d99bb5 100644 --- a/zeppelin-server/src/main/resources/shiro.ini +++ b/zeppelin-server/src/main/resources/shiro.ini @@ -18,14 +18,19 @@ [users] # List of users with their password allowed to access Zeppelin. # To use a different strategy (LDAP / Database / ...) check the shiro doc at http://shiro.apache.org/configuration.html#Configuration-INISections -admin = password +admin = password, admin +user1 = user1, role1 [urls] - # anon means the access is anonymous. # authcBasic means Basic Auth Security # To enfore security, comment the line below and uncomment the next one /** = anon -#/** = authcBasic +#/** = authc +[roles] +role1 = * +role2 = * +role3 = * +admin = * diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java index c767eb05786..6d4fb2c5472 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java @@ -30,7 +30,9 @@ import org.apache.zeppelin.notebook.Paragraph; import org.apache.zeppelin.scheduler.Job.Status; import org.apache.zeppelin.server.ZeppelinServer; +import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; @@ -47,6 +49,7 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class InterpreterRestApiTest extends AbstractTestRestApi { Gson gson = new Gson(); + AuthenticationInfo anonymous; @BeforeClass public static void init() throws Exception { @@ -58,6 +61,11 @@ public static void destroy() throws Exception { AbstractTestRestApi.shutDown(); } + @Before + public void setUp() { + anonymous = new AuthenticationInfo("anonymous"); + } + @Test public void getAvailableInterpreters() throws IOException { // when @@ -90,7 +98,7 @@ public void testSettingsCRUD() throws IOException { String jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"}," + "\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]," + "\"dependencies\":[]," + - "\"option\": { \"remote\": true, \"perNoteSession\": false }}"; + "\"option\": { \"remote\": true, \"session\": false }}"; PostMethod post = httpPost("/interpreter/setting/", jsonRequest); LOG.info("testSettingCRUD create response\n" + post.getResponseBodyAsString()); assertThat("test create method:", post, isCreated()); @@ -106,7 +114,7 @@ public void testSettingsCRUD() throws IOException { jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"Otherpropvalue\"}," + "\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]," + "\"dependencies\":[]," + - "\"option\": { \"remote\": true, \"perNoteSession\": false }}"; + "\"option\": { \"remote\": true, \"session\": false }}"; PutMethod put = httpPut("/interpreter/setting/" + newSettingId, jsonRequest); LOG.info("testSettingCRUD update response\n" + put.getResponseBodyAsString()); assertThat("test update method:", put, isAllowed()); @@ -131,7 +139,7 @@ public void testSettingsCreateWithEmptyJson() throws IOException { @Test public void testInterpreterAutoBinding() throws IOException { // create note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); // check interpreter is binded GetMethod get = httpGet("/notebook/interpreter/bind/" + note.getId()); @@ -144,13 +152,13 @@ public void testInterpreterAutoBinding() throws IOException { get.releaseConnection(); //cleanup - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testInterpreterRestart() throws IOException, InterruptedException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); note.addParagraph(); Paragraph p = note.getLastParagraph(); Map config = p.getConfig(); @@ -159,6 +167,7 @@ public void testInterpreterRestart() throws IOException, InterruptedException { // run markdown paragraph p.setConfig(config); p.setText("%md markdown"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); while (p.getStatus() != Status.FINISHED) { Thread.sleep(100); @@ -181,13 +190,14 @@ public void testInterpreterRestart() throws IOException, InterruptedException { p = note.addParagraph(); p.setConfig(config); p.setText("%md markdown restarted"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); while (p.getStatus() != Status.FINISHED) { Thread.sleep(100); } assertEquals("

markdown restarted

\n", p.getResult().message()); //cleanup - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java index d7f55f54744..9383569fae1 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/NotebookRestApiTest.java @@ -28,7 +28,9 @@ import org.apache.zeppelin.notebook.NotebookAuthorization; import org.apache.zeppelin.notebook.NotebookAuthorizationInfoSaving; import org.apache.zeppelin.server.ZeppelinServer; +import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; @@ -49,6 +51,7 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class NotebookRestApiTest extends AbstractTestRestApi { Gson gson = new Gson(); + AuthenticationInfo anonymous; @BeforeClass public static void init() throws Exception { @@ -60,9 +63,14 @@ public static void destroy() throws Exception { AbstractTestRestApi.shutDown(); } + @Before + public void setUp() { + anonymous = new AuthenticationInfo("anonymous"); + } + @Test public void testPermissions() throws IOException { - Note note1 = ZeppelinServer.notebook.createNote(null); + Note note1 = ZeppelinServer.notebook.createNote(anonymous); // Set only readers String jsonRequest = "{\"readers\":[\"admin-team\"],\"owners\":[]," + "\"writers\":[]}"; @@ -85,7 +93,7 @@ public void testPermissions() throws IOException { get.releaseConnection(); - Note note2 = ZeppelinServer.notebook.createNote(null); + Note note2 = ZeppelinServer.notebook.createNote(anonymous); // Set only writers jsonRequest = "{\"readers\":[],\"owners\":[]," + "\"writers\":[\"admin-team\"]}"; @@ -119,14 +127,14 @@ public void testPermissions() throws IOException { assertEquals(authInfo.get("owners"), Lists.newArrayList()); get.releaseConnection(); //cleanup - ZeppelinServer.notebook.removeNote(note1.getId(), null); - ZeppelinServer.notebook.removeNote(note2.getId(), null); + ZeppelinServer.notebook.removeNote(note1.getId(), anonymous); + ZeppelinServer.notebook.removeNote(note2.getId(), anonymous); } @Test public void testGetNoteParagraphJobStatus() throws IOException { - Note note1 = ZeppelinServer.notebook.createNote(null); + Note note1 = ZeppelinServer.notebook.createNote(anonymous); note1.addParagraph(); String paragraphId = note1.getLastParagraph().getId(); @@ -142,13 +150,13 @@ public void testGetNoteParagraphJobStatus() throws IOException { assertEquals(paragraphStatus.get("status"), "READY"); //cleanup - ZeppelinServer.notebook.removeNote(note1.getId(), null); + ZeppelinServer.notebook.removeNote(note1.getId(), anonymous); } @Test public void testCloneNotebook() throws IOException { - Note note1 = ZeppelinServer.notebook.createNote(null); + Note note1 = ZeppelinServer.notebook.createNote(anonymous); PostMethod post = httpPost("/notebook/" + note1.getId(), ""); LOG.info("testCloneNotebook response\n" + post.getResponseBodyAsString()); assertThat(post, isCreated()); @@ -167,8 +175,8 @@ public void testCloneNotebook() throws IOException { get.releaseConnection(); //cleanup - ZeppelinServer.notebook.removeNote(note1.getId(), null); - ZeppelinServer.notebook.removeNote(clonedNotebookId, null); + ZeppelinServer.notebook.removeNote(note1.getId(), anonymous); + ZeppelinServer.notebook.removeNote(clonedNotebookId, anonymous); } } diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java index ffcbf2a0f1a..c2606f82494 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java @@ -34,6 +34,7 @@ import org.apache.zeppelin.server.ZeppelinServer; import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; @@ -51,6 +52,7 @@ @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class ZeppelinRestApiTest extends AbstractTestRestApi { Gson gson = new Gson(); + AuthenticationInfo anonymous; @BeforeClass public static void init() throws Exception { @@ -62,6 +64,11 @@ public static void destroy() throws Exception { AbstractTestRestApi.shutDown(); } + @Before + public void setUp() { + anonymous = new AuthenticationInfo("anonymous"); + } + /*** * ROOT API TEST ***/ @@ -78,7 +85,7 @@ public void getApiRoot() throws IOException { public void testGetNotebookInfo() throws IOException { LOG.info("testGetNotebookInfo"); // Create note to get info - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName("note"); Paragraph paragraph = note.addParagraph(); @@ -87,7 +94,7 @@ public void testGetNotebookInfo() throws IOException { paragraph.setConfig(config); String paragraphText = "%md This is my new paragraph in my new note"; paragraph.setText(paragraphText); - note.persist(null); + note.persist(anonymous); String sourceNoteID = note.getId(); GetMethod get = httpGet("/notebook/" + sourceNoteID); @@ -106,7 +113,7 @@ public void testGetNotebookInfo() throws IOException { assertTrue(paragraphs.size() > 0); assertEquals(paragraphText, paragraphs.get(0).get("text")); // - ZeppelinServer.notebook.removeNote(sourceNoteID, null); + ZeppelinServer.notebook.removeNote(sourceNoteID, anonymous); } @Test @@ -156,7 +163,7 @@ public void testNotebookCreateWithParagraphs() throws IOException { assertTrue("paragraph text check failed", p.getText().startsWith("text")); } // cleanup - ZeppelinServer.notebook.removeNote(newNotebookId, null); + ZeppelinServer.notebook.removeNote(newNotebookId, anonymous); post.releaseConnection(); } @@ -183,7 +190,7 @@ private void testNotebookCreate(String noteName) throws IOException { } assertEquals("compare note name", expectedNoteName, newNoteName); // cleanup - ZeppelinServer.notebook.removeNote(newNotebookId, null); + ZeppelinServer.notebook.removeNote(newNotebookId, anonymous); post.releaseConnection(); } @@ -192,7 +199,7 @@ private void testNotebookCreate(String noteName) throws IOException { public void testDeleteNote() throws IOException { LOG.info("testDeleteNote"); //Create note and get ID - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); String noteId = note.getId(); testDeleteNotebook(noteId); } @@ -208,7 +215,7 @@ public void testDeleteNoteBadId() throws IOException { @Test public void testExportNotebook() throws IOException { LOG.info("testExportNotebook"); - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName("source note for export"); Paragraph paragraph = note.addParagraph(); @@ -216,7 +223,7 @@ public void testExportNotebook() throws IOException { config.put("enabled", true); paragraph.setConfig(config); paragraph.setText("%md This is my new paragraph in my new note"); - note.persist(null); + note.persist(anonymous); String sourceNoteID = note.getId(); // Call export Notebook REST API GetMethod get = httpGet("/notebook/export/" + sourceNoteID); @@ -230,7 +237,7 @@ public void testExportNotebook() throws IOException { String exportJSON = (String) resp.get("body"); assertNotNull("Can not find new notejson", exportJSON); LOG.info("export JSON:=" + exportJSON); - ZeppelinServer.notebook.removeNote(sourceNoteID, null); + ZeppelinServer.notebook.removeNote(sourceNoteID, anonymous); get.releaseConnection(); } @@ -241,7 +248,7 @@ public void testImportNotebook() throws IOException { String noteName = "source note for import"; LOG.info("testImortNotebook"); // create test notebook - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName(noteName); Paragraph paragraph = note.addParagraph(); @@ -249,7 +256,7 @@ public void testImportNotebook() throws IOException { config.put("enabled", true); paragraph.setConfig(config); paragraph.setText("%md This is my new paragraph in my new note"); - note.persist(null); + note.persist(anonymous); String sourceNoteID = note.getId(); // get note content as JSON String oldJson = getNoteContent(sourceNoteID); @@ -267,8 +274,8 @@ public void testImportNotebook() throws IOException { assertEquals("Compare paragraphs count", note.getParagraphs().size(), newNote.getParagraphs() .size()); // cleanup - ZeppelinServer.notebook.removeNote(note.getId(), null); - ZeppelinServer.notebook.removeNote(newNote.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); + ZeppelinServer.notebook.removeNote(newNote.getId(), anonymous); importPost.releaseConnection(); } @@ -303,7 +310,7 @@ private void testDeleteNotebook(String notebookId) throws IOException { public void testCloneNotebook() throws IOException, CloneNotSupportedException, IllegalArgumentException { LOG.info("testCloneNotebook"); // Create note to clone - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName("source note for clone"); Paragraph paragraph = note.addParagraph(); @@ -311,7 +318,7 @@ public void testCloneNotebook() throws IOException, CloneNotSupportedException, config.put("enabled", true); paragraph.setConfig(config); paragraph.setText("%md This is my new paragraph in my new note"); - note.persist(null); + note.persist(anonymous); String sourceNoteID = note.getId(); String noteName = "clone Note Name"; @@ -331,8 +338,8 @@ public void testCloneNotebook() throws IOException, CloneNotSupportedException, assertEquals("Compare note names", noteName, newNote.getName()); assertEquals("Compare paragraphs count", note.getParagraphs().size(), newNote.getParagraphs().size()); //cleanup - ZeppelinServer.notebook.removeNote(note.getId(), null); - ZeppelinServer.notebook.removeNote(newNote.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); + ZeppelinServer.notebook.removeNote(newNote.getId(), anonymous); post.releaseConnection(); } @@ -354,7 +361,7 @@ public void testListNotebooks() throws IOException { public void testNoteJobs() throws IOException, InterruptedException { LOG.info("testNoteJobs"); // Create note to run test. - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName("note for run test"); Paragraph paragraph = note.addParagraph(); @@ -364,7 +371,7 @@ public void testNoteJobs() throws IOException, InterruptedException { paragraph.setConfig(config); paragraph.setText("%md This is test paragraph."); - note.persist(null); + note.persist(anonymous); String noteID = note.getId(); note.runAll(); @@ -402,14 +409,14 @@ public void testNoteJobs() throws IOException, InterruptedException { Thread.sleep(1000); //cleanup - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testGetNotebookJob() throws IOException, InterruptedException { LOG.info("testGetNotebookJob"); // Create note to run test. - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName("note for run test"); Paragraph paragraph = note.addParagraph(); @@ -419,7 +426,8 @@ public void testGetNotebookJob() throws IOException, InterruptedException { paragraph.setConfig(config); paragraph.setText("%sh sleep 1"); - note.persist(null); + paragraph.setAuthenticationInfo(anonymous); + note.persist(anonymous); String noteID = note.getId(); note.runAll(); @@ -455,14 +463,14 @@ public void testGetNotebookJob() throws IOException, InterruptedException { } } - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testRunParagraphWithParams() throws IOException, InterruptedException { LOG.info("testRunParagraphWithParams"); // Create note to run test. - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); assertNotNull("can't create new note", note); note.setName("note for run test"); Paragraph paragraph = note.addParagraph(); @@ -472,7 +480,7 @@ public void testRunParagraphWithParams() throws IOException, InterruptedExceptio paragraph.setConfig(config); paragraph.setText("%spark\nval param = z.input(\"param\").toString\nprintln(param)"); - note.persist(null); + note.persist(anonymous); String noteID = note.getId(); note.runAll(); @@ -500,13 +508,13 @@ public void testRunParagraphWithParams() throws IOException, InterruptedExceptio assertEquals("world", params.get("param2")); //cleanup - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test - public void testCronJobs() throws InterruptedException, IOException{ + public void testJobs() throws InterruptedException, IOException{ // create a note and a paragraph - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); note.setName("note for run test"); Paragraph paragraph = note.addParagraph(); @@ -550,18 +558,18 @@ public void testCronJobs() throws InterruptedException, IOException{ DeleteMethod deleteCron = httpDelete("/notebook/cron/" + note.getId()); assertThat("", deleteCron, isAllowed()); deleteCron.releaseConnection(); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testRegressionZEPPELIN_527() throws IOException { - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); note.setName("note for run test"); Paragraph paragraph = note.addParagraph(); paragraph.setText("%spark\nval param = z.input(\"param\").toString\nprintln(param)"); - note.persist(null); + note.persist(anonymous); GetMethod getNoteJobs = httpGet("/notebook/job/" + note.getId()); assertThat("test notebook jobs run:", getNoteJobs, isAllowed()); @@ -572,12 +580,12 @@ public void testRegressionZEPPELIN_527() throws IOException { assertFalse(body.get(0).containsKey("finished")); getNoteJobs.releaseConnection(); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testInsertParagraph() throws IOException { - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); String jsonRequest = "{\"title\": \"title1\", \"text\": \"text1\"}"; PostMethod post = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest); @@ -612,17 +620,17 @@ public void testInsertParagraph() throws IOException { assertEquals("title2", paragraphAtIdx0.getTitle()); assertEquals("text2", paragraphAtIdx0.getText()); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testGetParagraph() throws IOException { - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); Paragraph p = note.addParagraph(); p.setTitle("hello"); p.setText("world"); - note.persist(null); + note.persist(anonymous); GetMethod get = httpGet("/notebook/" + note.getId() + "/paragraph/" + p.getId()); LOG.info("testGetParagraph response\n" + get.getResponseBodyAsString()); @@ -641,12 +649,12 @@ public void testGetParagraph() throws IOException { assertEquals("hello", body.get("title")); assertEquals("world", body.get("text")); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testMoveParagraph() throws IOException { - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); Paragraph p = note.addParagraph(); p.setTitle("title1"); @@ -656,7 +664,7 @@ public void testMoveParagraph() throws IOException { p2.setTitle("title2"); p2.setText("text2"); - note.persist(null); + note.persist(anonymous); PostMethod post = httpPost("/notebook/" + note.getId() + "/paragraph/" + p2.getId() + "/move/" + 0, ""); assertThat("Test post method: ", post, isAllowed()); @@ -673,18 +681,18 @@ public void testMoveParagraph() throws IOException { assertThat("Test post method: ", post2, isBadRequest()); post.releaseConnection(); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void testDeleteParagraph() throws IOException { - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); Paragraph p = note.addParagraph(); p.setTitle("title1"); p.setText("text1"); - note.persist(null); + note.persist(anonymous); DeleteMethod delete = httpDelete("/notebook/" + note.getId() + "/paragraph/" + p.getId()); assertThat("Test delete method: ", delete, isAllowed()); @@ -694,7 +702,7 @@ public void testDeleteParagraph() throws IOException { Paragraph retrParagrah = retrNote.getParagraph(p.getId()); assertNull("paragraph should be deleted", retrParagrah); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test @@ -710,12 +718,12 @@ public void testSearch() throws IOException { String username = body.get("principal"); getSecurityTicket.releaseConnection(); - Note note1 = ZeppelinServer.notebook.createNote(null); + Note note1 = ZeppelinServer.notebook.createNote(anonymous); String jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 1\"}"; PostMethod postNotebookText = httpPost("/notebook/" + note1.getId() + "/paragraph", jsonRequest); postNotebookText.releaseConnection(); - Note note2 = ZeppelinServer.notebook.createNote(null); + Note note2 = ZeppelinServer.notebook.createNote(anonymous); jsonRequest = "{\"title\": \"title1\", \"text\": \"ThisIsToTestSearchMethodWithPermissions 2\"}"; postNotebookText = httpPost("/notebook/" + note2.getId() + "/paragraph", jsonRequest); postNotebookText.releaseConnection(); @@ -757,13 +765,13 @@ public void testSearch() throws IOException { getPermission.releaseConnection(); } searchNotebook.releaseConnection(); - ZeppelinServer.notebook.removeNote(note1.getId(), null); - ZeppelinServer.notebook.removeNote(note2.getId(), null); + ZeppelinServer.notebook.removeNote(note1.getId(), anonymous); + ZeppelinServer.notebook.removeNote(note2.getId(), anonymous); } @Test public void testTitleSearch() throws IOException { - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); String jsonRequest = "{\"title\": \"testTitleSearchOfParagraph\", \"text\": \"ThisIsToTestSearchMethodWithTitle \"}"; PostMethod postNotebookText = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest); postNotebookText.releaseConnection(); @@ -784,7 +792,7 @@ public void testTitleSearch() throws IOException { } assertEquals("Paragraph title hits must be at-least one", true, numberOfTitleHits >= 1); searchNotebook.releaseConnection(); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } } diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java index 5084ae73719..740ef4066c4 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinSparkClusterTest.java @@ -31,7 +31,9 @@ import org.apache.zeppelin.notebook.Paragraph; import org.apache.zeppelin.scheduler.Job.Status; import org.apache.zeppelin.server.ZeppelinServer; +import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.AfterClass; +import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -43,6 +45,7 @@ */ public class ZeppelinSparkClusterTest extends AbstractTestRestApi { Gson gson = new Gson(); + AuthenticationInfo anonymous; @BeforeClass public static void init() throws Exception { @@ -54,6 +57,11 @@ public static void destroy() throws Exception { AbstractTestRestApi.shutDown(); } + @Before + public void setUp() { + anonymous = new AuthenticationInfo("anonymous"); + } + private void waitForFinish(Paragraph p) { while (p.getStatus() != Status.FINISHED && p.getStatus() != Status.ERROR @@ -69,7 +77,7 @@ private void waitForFinish(Paragraph p) { @Test public void basicRDDTransformationAndActionTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); // run markdown paragraph, again Paragraph p = note.addParagraph(); @@ -77,17 +85,18 @@ public void basicRDDTransformationAndActionTest() throws IOException { config.put("enabled", true); p.setConfig(config); p.setText("%spark print(sc.parallelize(1 to 10).reduce(_ + _))"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); assertEquals("55", p.getResult().message()); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void sparkSQLTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); int sparkVersion = getSparkVersionNumber(note); // DataFrame API is available from spark 1.3 if (sparkVersion >= 13) { @@ -98,6 +107,7 @@ public void sparkSQLTest() throws IOException { p.setConfig(config); p.setText("%spark val df=sqlContext.createDataFrame(Seq((\"hello\",20)))\n" + "df.collect()"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -111,6 +121,7 @@ public void sparkSQLTest() throws IOException { p.setConfig(config); p.setText("%spark val df=sqlContext.createDataFrame(Seq((\"hello\",20)))\n" + "z.show(df)"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -125,20 +136,21 @@ public void sparkSQLTest() throws IOException { p.setConfig(config); p.setText("%spark val ds=spark.createDataset(Seq((\"hello\",20)))\n" + "z.show(ds)"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); assertEquals(InterpreterResult.Type.TABLE, p.getResult().type()); assertEquals("_1\t_2\nhello\t20\n", p.getResult().message()); } - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } } @Test public void sparkRTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); int sparkVersion = getSparkVersionNumber(note); if (isSparkR() && sparkVersion >= 14) { // sparkr supported from 1.4.0 @@ -165,19 +177,20 @@ public void sparkRTest() throws IOException { "df <- createDataFrame(" + sqlContextName + ", localDF)\n" + "count(df)" ); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); System.err.println("sparkRTest=" + p.getResult().message()); assertEquals(Status.FINISHED, p.getStatus()); assertEquals("[1] 3", p.getResult().message()); } - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void pySparkTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); note.setName("note"); int sparkVersion = getSparkVersionNumber(note); @@ -188,6 +201,7 @@ public void pySparkTest() throws IOException { config.put("enabled", true); p.setConfig(config); p.setText("%pyspark print(sc.parallelize(range(1, 11)).reduce(lambda a, b: a + b))"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -201,6 +215,7 @@ public void pySparkTest() throws IOException { p.setText("%pyspark from pyspark.sql import Row\n" + "df=sqlContext.createDataFrame([Row(id=1, age=20)])\n" + "df.collect()"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -214,6 +229,7 @@ public void pySparkTest() throws IOException { p.setText("%pyspark from pyspark.sql import Row\n" + "df=sqlContext.createDataFrame([Row(id=1, age=20)])\n" + "z.show(df)"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -228,6 +244,7 @@ public void pySparkTest() throws IOException { p.setConfig(config); p.setText("%pyspark sqlContext.udf.register(\"f1\", lambda x: len(x))\n" + "sqlContext.sql(\"select f1(\\\"abc\\\") as len\").collect()"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -242,6 +259,7 @@ public void pySparkTest() throws IOException { p.setText("%pyspark from pyspark.sql import Row\n" + "df=sqlContext.createDataFrame([Row(id=1, age=20)])\n" + "df.collect()"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); @@ -255,19 +273,20 @@ public void pySparkTest() throws IOException { // use SQLContext to register UDF but use this UDF through SparkSession p.setText("%pyspark sqlContext.udf.register(\"f1\", lambda x: len(x))\n" + "spark.sql(\"select f1(\\\"abc\\\") as len\").collect()"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); assertEquals("[Row(len=u'3')]\n", p.getResult().message()); } } - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void pySparkAutoConvertOptionTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); note.setName("note"); int sparkVersionNumber = getSparkVersionNumber(note); @@ -286,33 +305,37 @@ public void pySparkAutoConvertOptionTest() throws IOException { p.setText("%pyspark\nfrom pyspark.sql.functions import *\n" + "print(" + sqlContextName + ".range(0, 10).withColumn('uniform', rand(seed=10) * 3.14).count())"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); assertEquals("10\n", p.getResult().message()); } - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void zRunTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); Paragraph p0 = note.addParagraph(); Map config0 = p0.getConfig(); config0.put("enabled", true); p0.setConfig(config0); p0.setText("%spark z.run(1)"); + p0.setAuthenticationInfo(anonymous); Paragraph p1 = note.addParagraph(); Map config1 = p1.getConfig(); config1.put("enabled", true); p1.setConfig(config1); p1.setText("%spark val a=10"); + p1.setAuthenticationInfo(anonymous); Paragraph p2 = note.addParagraph(); Map config2 = p2.getConfig(); config2.put("enabled", true); p2.setConfig(config2); p2.setText("%spark print(a)"); + p2.setAuthenticationInfo(anonymous); note.run(p0.getId()); waitForFinish(p0); @@ -323,13 +346,13 @@ public void zRunTest() throws IOException { assertEquals(Status.FINISHED, p2.getStatus()); assertEquals("10", p2.getResult().message()); - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } @Test public void pySparkDepLoaderTest() throws IOException { // create new note - Note note = ZeppelinServer.notebook.createNote(null); + Note note = ZeppelinServer.notebook.createNote(anonymous); int sparkVersionNumber = getSparkVersionNumber(note); if (isPyspark() && sparkVersionNumber >= 14) { @@ -350,6 +373,7 @@ public void pySparkDepLoaderTest() throws IOException { config.put("enabled", true); p0.setConfig(config); p0.setText("%dep z.load(\"com.databricks:spark-csv_2.11:1.2.0\")"); + p0.setAuthenticationInfo(anonymous); note.run(p0.getId()); waitForFinish(p0); assertEquals(Status.FINISHED, p0.getStatus()); @@ -370,13 +394,14 @@ public void pySparkDepLoaderTest() throws IOException { "from pyspark.sql import SQLContext\n" + "print(" + sqlContextName + ".read.format('com.databricks.spark.csv')" + ".load('"+ tmpFile.getAbsolutePath() +"').count())"); + p1.setAuthenticationInfo(anonymous); note.run(p1.getId()); waitForFinish(p1); assertEquals(Status.FINISHED, p1.getStatus()); assertEquals("2\n", p1.getResult().message()); } - ZeppelinServer.notebook.removeNote(note.getId(), null); + ZeppelinServer.notebook.removeNote(note.getId(), anonymous); } /** @@ -390,6 +415,7 @@ private int getSparkVersionNumber(Note note) { config.put("enabled", true); p.setConfig(config); p.setText("%spark print(sc.version)"); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); waitForFinish(p); assertEquals(Status.FINISHED, p.getStatus()); diff --git a/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java b/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java index 01a24e2e1de..caac04349e2 100644 --- a/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java +++ b/zeppelin-server/src/test/java/org/apache/zeppelin/socket/NotebookServerTest.java @@ -31,6 +31,7 @@ import org.apache.zeppelin.notebook.socket.Message.OP; import org.apache.zeppelin.rest.AbstractTestRestApi; import org.apache.zeppelin.server.ZeppelinServer; +import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -57,6 +58,7 @@ public class NotebookServerTest extends AbstractTestRestApi { private static NotebookServer notebookServer; private static Gson gson; private HttpServletRequest mockRequest; + private AuthenticationInfo anonymous; @BeforeClass public static void init() throws Exception { @@ -74,6 +76,7 @@ public static void destroy() throws Exception { @Before public void setUp() { mockRequest = mock(HttpServletRequest.class); + anonymous = new AuthenticationInfo("anonymous"); } @Test @@ -94,14 +97,14 @@ public void checkInvalidOrigin(){ @Test public void testMakeSureNoAngularObjectBroadcastToWebsocketWhoFireTheEvent() throws IOException { // create a notebook - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); // get reference to interpreterGroup InterpreterGroup interpreterGroup = null; List settings = notebook.getInterpreterFactory().getInterpreterSettings(note1.getId()); for (InterpreterSetting setting : settings) { if (setting.getName().equals("md")) { - interpreterGroup = setting.getInterpreterGroup("sharedProcess"); + interpreterGroup = setting.getInterpreterGroup("anonymous", "sharedProcess"); break; } } @@ -109,6 +112,7 @@ public void testMakeSureNoAngularObjectBroadcastToWebsocketWhoFireTheEvent() thr // start interpreter process Paragraph p1 = note1.addParagraph(); p1.setText("%md start remote interpreter process"); + p1.setAuthenticationInfo(anonymous); note1.run(p1.getId()); // add angularObject @@ -144,7 +148,7 @@ public void testMakeSureNoAngularObjectBroadcastToWebsocketWhoFireTheEvent() thr verify(sock1, times(0)).send(anyString()); verify(sock2, times(1)).send(anyString()); - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Test @@ -167,7 +171,7 @@ public void testImportNotebook() throws IOException { assertNotEquals(null, notebook.getNote(note.getId())); assertEquals("Test Zeppelin notebook import", notebook.getNote(note.getId()).getName()); assertEquals("Test paragraphs import", notebook.getNote(note.getId()).getParagraphs().get(0).getText()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test diff --git a/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html index d0e0749360f..2638dd84e3a 100644 --- a/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html +++ b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html @@ -37,23 +37,31 @@

Create new interpreter

Option
+ + + + + + - Interpreter for note
diff --git a/zeppelin-web/src/app/interpreter/interpreter.controller.js b/zeppelin-web/src/app/interpreter/interpreter.controller.js index 3fe355fe1b8..0669ff8f38a 100644 --- a/zeppelin-web/src/app/interpreter/interpreter.controller.js +++ b/zeppelin-web/src/app/interpreter/interpreter.controller.js @@ -16,9 +16,9 @@ angular.module('zeppelinWebApp').controller('InterpreterCtrl', InterpreterCtrl); - InterpreterCtrl.$inject = ['$scope', '$http', 'baseUrlSrv', 'ngToast', '$timeout', '$route']; + InterpreterCtrl.$inject = ['$rootScope', '$scope', '$http', 'baseUrlSrv', 'ngToast', '$timeout', '$route']; - function InterpreterCtrl($scope, $http, baseUrlSrv, ngToast, $timeout, $route) { + function InterpreterCtrl($rootScope, $scope, $http, baseUrlSrv, ngToast, $timeout, $route) { var interpreterSettingsTmp = []; $scope.interpreterSettings = []; $scope.availableInterpreters = {}; @@ -156,7 +156,7 @@ interpreterSettingsTmp[index] = angular.copy($scope.interpreterSettings[index]); }; - $scope.setSessionOption = function(settingId, sessionOption) { + $scope.setPerNoteOption = function(settingId, sessionOption) { var option; if (settingId === undefined) { option = $scope.newInterpreterSetting.option; @@ -167,18 +167,21 @@ } if (sessionOption === 'isolated') { - option.perNoteSession = false; - option.perNoteProcess = true; + option.perNote = sessionOption; + option.session = false; + option.process = true; } else if (sessionOption === 'scoped') { - option.perNoteSession = true; - option.perNoteProcess = false; + option.perNote = sessionOption; + option.session = true; + option.process = false; } else { - option.perNoteSession = false; - option.perNoteProcess = false; + option.perNote = 'shared'; + option.session = false; + option.process = false; } }; - $scope.getSessionOption = function(settingId) { + $scope.setPerUserOption = function(settingId, sessionOption) { var option; if (settingId === undefined) { option = $scope.newInterpreterSetting.option; @@ -187,15 +190,115 @@ var setting = $scope.interpreterSettings[index]; option = setting.option; } - if (option.perNoteSession) { + + if (sessionOption === 'isolated') { + option.perUser = sessionOption; + option.session = false; + option.process = true; + } else if (sessionOption === 'scoped') { + option.perUser = sessionOption; + option.session = true; + option.process = false; + } else { + option.perUser = 'shared'; + option.session = false; + option.process = false; + } + }; + + $scope.getPerNoteOption = function(settingId) { + var option; + if (settingId === undefined) { + option = $scope.newInterpreterSetting.option; + } else { + var index = _.findIndex($scope.interpreterSettings, {'id': settingId}); + var setting = $scope.interpreterSettings[index]; + option = setting.option; + } + + if (option.perNote === 'scoped') { + return 'scoped'; + } else if (option.perNote === 'isolated') { + return 'isolated'; + } else { + return 'shared'; + } + }; + + $scope.getPerUserOption = function(settingId) { + var option; + if (settingId === undefined) { + option = $scope.newInterpreterSetting.option; + } else { + var index = _.findIndex($scope.interpreterSettings, {'id': settingId}); + var setting = $scope.interpreterSettings[index]; + option = setting.option; + } + + if (option.perUser === 'scoped') { return 'scoped'; - } else if (option.perNoteProcess) { + } else if (option.perUser === 'isolated') { return 'isolated'; } else { return 'shared'; } }; + $scope.getInterpreterRunningOption = function(settingId) { + var sharedModeName = 'shared'; + + var globallyModeName = 'Globally'; + var perNoteModeName = 'Per Note'; + var perUserModeName = 'Per User'; + + var option; + if (settingId === undefined) { + option = $scope.newInterpreterSetting.option; + } else { + var index = _.findIndex($scope.interpreterSettings, {'id': settingId}); + var setting = $scope.interpreterSettings[index]; + option = setting.option; + } + + var perNote = option.perNote; + var perUser = option.perUser; + + // Globally == shared_perNote + shared_perUser + if (perNote === sharedModeName && perUser === sharedModeName) { + return globallyModeName; + } + + if ($rootScope.ticket.ticket === 'anonymous' && $rootScope.ticket.roles === '[]') { + if (perNote !== undefined && typeof perNote === 'string' && perNote !== '') { + return perNoteModeName; + } + } else if ($rootScope.ticket.ticket !== 'anonymous') { + if (perNote !== undefined && typeof perNote === 'string' && perNote !== '') { + if (perUser !== undefined && typeof perUser === 'string' && perUser !== '') { + return perUserModeName; + } + return perNoteModeName; + } + } + + option.perNote = sharedModeName; + option.perUser = sharedModeName; + return globallyModeName; + }; + + $scope.setInterpreterRunningOption = function(settingId, isPerNoteMode, isPerUserMode) { + var option; + if (settingId === undefined) { + option = $scope.newInterpreterSetting.option; + } else { + var index = _.findIndex($scope.interpreterSettings, {'id': settingId}); + var setting = $scope.interpreterSettings[index]; + option = setting.option; + } + option.perNote = isPerNoteMode; + option.perUser = isPerUserMode; + }; + $scope.updateInterpreterSetting = function(form, settingId) { var thisConfirm = BootstrapDialog.confirm({ closable: false, @@ -402,8 +505,8 @@ remote: true, isExistingProcess: false, setPermission: false, - perNoteSession: false, - perNoteProcess: false + session: false, + process: false } }; diff --git a/zeppelin-web/src/app/interpreter/interpreter.html b/zeppelin-web/src/app/interpreter/interpreter.html index 57b305ee67c..e0e861343b9 100644 --- a/zeppelin-web/src/app/interpreter/interpreter.html +++ b/zeppelin-web/src/app/interpreter/interpreter.html @@ -141,40 +141,172 @@

{{setting.name}}

+
Option
- - - - - Interpreter for note +
+
+ The interpreter will be instantiated + + + + + in + + + + + process. + + + + + +
+
+   +
+
+
+
+ + + + And + + + + in + + + + + process. + + + +
+
+   +
+
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java index 5d9f301cae8..19081c9889e 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java @@ -121,6 +121,8 @@ public class InterpreterFactory implements InterpreterGroupFactory { private DependencyResolver depResolver; + private boolean shiroEnabled; + private Map env = new HashMap<>(); private Interpreter devInterpreter; @@ -128,18 +130,18 @@ public class InterpreterFactory implements InterpreterGroupFactory { public InterpreterFactory(ZeppelinConfiguration conf, AngularObjectRegistryListener angularObjectRegistryListener, RemoteInterpreterProcessListener remoteInterpreterProcessListener, - ApplicationEventListener appEventListener, DependencyResolver depResolver) - throws InterpreterException, IOException, RepositoryException { + ApplicationEventListener appEventListener, DependencyResolver depResolver, + boolean shiroEnabled) throws InterpreterException, IOException, RepositoryException { this(conf, new InterpreterOption(true), angularObjectRegistryListener, - remoteInterpreterProcessListener, appEventListener, depResolver); + remoteInterpreterProcessListener, appEventListener, depResolver, shiroEnabled); } public InterpreterFactory(ZeppelinConfiguration conf, InterpreterOption defaultOption, AngularObjectRegistryListener angularObjectRegistryListener, RemoteInterpreterProcessListener remoteInterpreterProcessListener, - ApplicationEventListener appEventListener, DependencyResolver depResolver) - throws InterpreterException, IOException, RepositoryException { + ApplicationEventListener appEventListener, DependencyResolver depResolver, + boolean shiroEnabled) throws InterpreterException, IOException, RepositoryException { this.conf = conf; this.defaultOption = defaultOption; this.angularObjectRegistryListener = angularObjectRegistryListener; @@ -147,6 +149,7 @@ public InterpreterFactory(ZeppelinConfiguration conf, InterpreterOption defaultO this.interpreterRepositories = depResolver.getRepos(); this.remoteInterpreterProcessListener = remoteInterpreterProcessListener; this.appEventListener = appEventListener; + this.shiroEnabled = shiroEnabled; String replsConf = conf.getString(ConfVars.ZEPPELIN_INTERPRETERS); interpreterClassList = replsConf.split(","); String groupOrder = conf.getString(ConfVars.ZEPPELIN_INTERPRETER_GROUP_ORDER); @@ -157,6 +160,8 @@ public InterpreterFactory(ZeppelinConfiguration conf, InterpreterOption defaultO gson = builder.create(); init(); + + logger.info("shiroEnabled: {}", shiroEnabled); } private void init() throws InterpreterException, IOException, RepositoryException { @@ -698,16 +703,18 @@ public InterpreterGroup createInterpreterGroup(String id, InterpreterOption opti return interpreterGroup; } - public void removeInterpretersForNote(InterpreterSetting interpreterSetting, String noteId) { - if (interpreterSetting.getOption().isPerNoteProcess()) { + public void removeInterpretersForNote(InterpreterSetting interpreterSetting, String user, + String noteId) { + InterpreterOption option = interpreterSetting.getOption(); + if (option.isProcess()) { interpreterSetting.closeAndRemoveInterpreterGroup(noteId); - } else if (interpreterSetting.getOption().isPerNoteSession()) { - InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(noteId); - - interpreterGroup.close(noteId); - interpreterGroup.destroy(noteId); + } else if (option.isSession()) { + InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(user, noteId); + String key = getInterpreterInstanceKey(user, noteId, interpreterSetting); + interpreterGroup.close(key); + interpreterGroup.destroy(key); synchronized (interpreterGroup) { - interpreterGroup.remove(noteId); + interpreterGroup.remove(key); interpreterGroup.notifyAll(); // notify createInterpreterForNote() } logger.info("Interpreter instance {} for note {} is removed", interpreterSetting.getName(), @@ -715,9 +722,9 @@ public void removeInterpretersForNote(InterpreterSetting interpreterSetting, Str } } - public void createInterpretersForNote(InterpreterSetting interpreterSetting, String noteId, - String key) { - InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(noteId); + public void createInterpretersForNote(InterpreterSetting interpreterSetting, String user, + String noteId, String key) { + InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(user, noteId); InterpreterOption option = interpreterSetting.getOption(); Properties properties = interpreterSetting.getProperties(); if (option.isExistingProcess) { @@ -861,8 +868,8 @@ public InterpreterSetting get(String name) { } } - private void putNoteInterpreterSettingBinding(String noteId, List settingList) - throws IOException { + private void putNoteInterpreterSettingBinding(String user, String noteId, + List settingList) throws IOException { List unBindedSettings = new LinkedList<>(); synchronized (interpreterSettings) { @@ -879,18 +886,18 @@ private void putNoteInterpreterSettingBinding(String noteId, List settin for (String settingId : unBindedSettings) { InterpreterSetting setting = get(settingId); - removeInterpretersForNote(setting, noteId); + removeInterpretersForNote(setting, user, noteId); } } } - public void removeNoteInterpreterSettingBinding(String noteId) { + public void removeNoteInterpreterSettingBinding(String user, String noteId) { synchronized (interpreterSettings) { List settingIds = (interpreterBindings.containsKey(noteId) ? interpreterBindings.remove(noteId) : Collections.emptyList()); for (String settingId : settingIds) { - this.removeInterpretersForNote(get(settingId), noteId); + this.removeInterpretersForNote(get(settingId), user, noteId); } } } @@ -1093,8 +1100,8 @@ private Interpreter createRemoteRepl(String interpreterPath, String noteId, Stri * @param ids InterpreterSetting id list * @throws IOException */ - public void setInterpreters(String noteId, List ids) throws IOException { - putNoteInterpreterSettingBinding(noteId, ids); + public void setInterpreters(String user, String noteId, List ids) throws IOException { + putNoteInterpreterSettingBinding(user, noteId, ids); } public List getInterpreters(String noteId) { @@ -1119,7 +1126,7 @@ public List getInterpreterSettings(String noteId) { return settings; } - public void closeNote(String noteId) { + public void closeNote(String user, String noteId) { // close interpreters in this note session List settings = getInterpreterSettings(noteId); if (settings == null || settings.size() == 0) { @@ -1128,28 +1135,37 @@ public void closeNote(String noteId) { logger.info("closeNote: {}", noteId); for (InterpreterSetting setting : settings) { - removeInterpretersForNote(setting, noteId); + removeInterpretersForNote(setting, user, noteId); } } - private String getInterpreterInstanceKey(String noteId, InterpreterSetting setting) { - if (setting.getOption().isExistingProcess()) { - return Constants.EXISTING_PROCESS; - } else if (setting.getOption().isPerNoteSession() || setting.getOption().isPerNoteProcess()) { - return noteId; + private String getInterpreterInstanceKey(String user, String noteId, InterpreterSetting setting) { + InterpreterOption option = setting.getOption(); + String key; + if (option.isExistingProcess()) { + key = Constants.EXISTING_PROCESS; + } else if (!option.perNoteShared()) { + key = noteId; + if (shiroEnabled && !option.perUserShared()) { + key = user + ":" + key; + } } else { - return SHARED_SESSION; + key = SHARED_SESSION; } + + logger.debug("Interpreter instance key: {}", key); + return key; } - private List createOrGetInterpreterList(String noteId, InterpreterSetting setting) { - InterpreterGroup interpreterGroup = setting.getInterpreterGroup(noteId); + private List createOrGetInterpreterList(String user, String noteId, + InterpreterSetting setting) { + InterpreterGroup interpreterGroup = setting.getInterpreterGroup(user, noteId); synchronized (interpreterGroup) { - String key = getInterpreterInstanceKey(noteId, setting); + String key = getInterpreterInstanceKey(user, noteId, setting); if (!interpreterGroup.containsKey(key)) { - createInterpretersForNote(setting, noteId, key); + createInterpretersForNote(setting, user, noteId, key); } - return interpreterGroup.get(getInterpreterInstanceKey(noteId, setting)); + return interpreterGroup.get(getInterpreterInstanceKey(user, noteId, setting)); } } @@ -1190,14 +1206,15 @@ private String getInterpreterClassFromInterpreterSetting(InterpreterSetting sett return null; } - private Interpreter getInterpreter(String noteId, InterpreterSetting setting, String name) { + private Interpreter getInterpreter(String user, String noteId, InterpreterSetting setting, + String name) { Preconditions.checkNotNull(noteId, "noteId should be not null"); Preconditions.checkNotNull(setting, "setting should be not null"); Preconditions.checkNotNull(name, "name should be not null"); String className; if (null != (className = getInterpreterClassFromInterpreterSetting(setting, name))) { - List interpreterGroup = createOrGetInterpreterList(noteId, setting); + List interpreterGroup = createOrGetInterpreterList(user, noteId, setting); for (Interpreter interpreter : interpreterGroup) { if (className.equals(interpreter.getClassName())) { return interpreter; @@ -1207,7 +1224,7 @@ private Interpreter getInterpreter(String noteId, InterpreterSetting setting, St return null; } - public Interpreter getInterpreter(String noteId, String replName) { + public Interpreter getInterpreter(String user, String noteId, String replName) { List settings = getInterpreterSettings(noteId); InterpreterSetting setting; Interpreter interpreter; @@ -1220,7 +1237,7 @@ public Interpreter getInterpreter(String noteId, String replName) { // get default settings (first available) // TODO(jl): Fix it in case of returning null InterpreterSetting defaultSettings = getDefaultInterpreterSetting(settings); - return createOrGetInterpreterList(noteId, defaultSettings).get(0); + return createOrGetInterpreterList(user, noteId, defaultSettings).get(0); } String[] replNameSplit = replName.split("\\."); @@ -1233,7 +1250,7 @@ public Interpreter getInterpreter(String noteId, String replName) { setting = getInterpreterSettingByGroup(settings, group); if (null != setting) { - interpreter = getInterpreter(noteId, setting, name); + interpreter = getInterpreter(user, noteId, setting, name); if (null != interpreter) { return interpreter; @@ -1248,7 +1265,7 @@ public Interpreter getInterpreter(String noteId, String replName) { // TODO(jl): Handle with noteId to support defaultInterpreter per note. setting = getDefaultInterpreterSetting(settings); - interpreter = getInterpreter(noteId, setting, replName); + interpreter = getInterpreter(user, noteId, setting, replName); if (null != interpreter) { return interpreter; @@ -1259,7 +1276,7 @@ public Interpreter getInterpreter(String noteId, String replName) { setting = getInterpreterSettingByGroup(settings, replName); if (null != setting) { - List interpreters = createOrGetInterpreterList(noteId, setting); + List interpreters = createOrGetInterpreterList(user, noteId, setting); if (null != interpreters) { return interpreters.get(0); } @@ -1268,7 +1285,7 @@ public Interpreter getInterpreter(String noteId, String replName) { // Support the legacy way to use it for (InterpreterSetting s : settings) { if (s.getGroup().equals(replName)) { - List interpreters = createOrGetInterpreterList(noteId, s); + List interpreters = createOrGetInterpreterList(user, noteId, s); if (null != interpreters) { return interpreters.get(0); } @@ -1330,8 +1347,8 @@ public void setEnv(Map env) { this.env = env; } - public Map getEditorSetting(String noteId, String replName) { - Interpreter intp = getInterpreter(noteId, replName); + public Map getEditorSetting(String user, String noteId, String replName) { + Interpreter intp = getInterpreter(user, noteId, replName); Map editor = Maps.newHashMap( ImmutableMap.builder() .put("language", "text").build()); diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java index d013a883107..e5c0f51a6d0 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java @@ -17,18 +17,25 @@ package org.apache.zeppelin.interpreter; +import com.google.common.base.Preconditions; + import java.util.List; /** * */ public class InterpreterOption { + public static final transient String SHARED = "shared"; + public static final transient String SCOPED = "scoped"; + public static final transient String ISOLATED = "isolated"; + boolean remote; String host = null; int port = -1; - boolean perNoteSession; - boolean perNoteProcess; - + + String perNote; + String perUser; + boolean isExistingProcess; boolean setPermission; List users; @@ -62,11 +69,21 @@ public List getUsers() { } public InterpreterOption() { - remote = false; + this(false); } public InterpreterOption(boolean remote) { + this(remote, SHARED, SHARED); + } + + public InterpreterOption(boolean remote, String perUser, String perNote) { + Preconditions.checkNotNull(remote); + Preconditions.checkNotNull(perUser); + Preconditions.checkNotNull(perNote); + this.remote = remote; + this.perUser = perUser; + this.perNote = perNote; } public boolean isRemote() { @@ -77,14 +94,6 @@ public void setRemote(boolean remote) { this.remote = remote; } - public boolean isPerNoteSession() { - return perNoteSession; - } - - public void setPerNoteSession(boolean perNoteSession) { - this.perNoteSession = perNoteSession; - } - public String getHost() { return host; } @@ -93,11 +102,44 @@ public int getPort() { return port; } - public boolean isPerNoteProcess() { - return perNoteProcess; + + public boolean perUserShared() { + return SHARED.equals(perUser); + } + + public boolean perUserScoped() { + return SCOPED.equals(perUser); + } + + public boolean perUserIsolated() { + return ISOLATED.equals(perUser); + } + + public boolean perNoteShared() { + return SHARED.equals(perNote); + } + + public boolean perNoteScoped() { + return SCOPED.equals(perNote); + } + + public boolean perNoteIsolated() { + return ISOLATED.equals(perNote); + } + + public boolean isProcess() { + return perUserIsolated() || perNoteIsolated(); + } + + public boolean isSession() { + return perUserScoped() || perNoteScoped(); + } + + public void setPerNote(String perNote) { + this.perNote = perNote; } - public void setPerNoteProcess(boolean perNoteProcess) { - this.perNoteProcess = perNoteProcess; + public void setPerUser(String perUser) { + this.perUser = perUser; } } diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java index 65f60cd1a6e..4611559b0b7 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java @@ -24,8 +24,11 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.concurrent.locks.ReentrantReadWriteLock; import com.google.gson.annotations.SerializedName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.apache.zeppelin.dep.Dependency; @@ -35,6 +38,7 @@ * Interpreter settings */ public class InterpreterSetting { + private static final Logger logger = LoggerFactory.getLogger(InterpreterSetting.class); private static final String SHARED_PROCESS = "shared_process"; private String id; private String name; @@ -51,13 +55,19 @@ public class InterpreterSetting { @Deprecated private transient InterpreterGroupFactory interpreterGroupFactory; - public InterpreterSetting() { + private final transient ReentrantReadWriteLock.ReadLock interpreterGroupReadLock; + private final transient ReentrantReadWriteLock.WriteLock interpreterGroupWriteLock; + public InterpreterSetting() { + ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + interpreterGroupReadLock = lock.readLock(); + interpreterGroupWriteLock = lock.writeLock(); } public InterpreterSetting(String id, String name, String group, List interpreterInfos, Properties properties, List dependencies, InterpreterOption option, String path) { + this(); this.id = id; this.name = name; this.group = group; @@ -96,40 +106,59 @@ String getGroup() { return group; } - private String getInterpreterProcessKey(String noteId) { + private String getInterpreterProcessKey(String user, String noteId) { + InterpreterOption option = getOption(); + String key; if (getOption().isExistingProcess) { - return Constants.EXISTING_PROCESS; - } else if (getOption().isPerNoteProcess()) { - return noteId; + key = Constants.EXISTING_PROCESS; + } else if (getOption().isProcess()) { + key = (option.perUserIsolated() ? user : "") + ":" + (option.perNoteIsolated() ? noteId : ""); } else { - return SHARED_PROCESS; + key = SHARED_PROCESS; } + + logger.debug("getInterpreterProcessKey: {}", key); + return key; } - public InterpreterGroup getInterpreterGroup(String noteId) { - String key = getInterpreterProcessKey(noteId); - synchronized (interpreterGroupRef) { - if (!interpreterGroupRef.containsKey(key)) { - String interpreterGroupId = getId() + ":" + key; - InterpreterGroup intpGroup = - interpreterGroupFactory.createInterpreterGroup(interpreterGroupId, getOption()); - interpreterGroupRef.put(key, intpGroup); - } + public InterpreterGroup getInterpreterGroup(String user, String noteId) { + String key = getInterpreterProcessKey(user, noteId); + if (!interpreterGroupRef.containsKey(key)) { + String interpreterGroupId = getId() + ":" + key; + InterpreterGroup intpGroup = + interpreterGroupFactory.createInterpreterGroup(interpreterGroupId, getOption()); + + interpreterGroupWriteLock.lock(); + interpreterGroupRef.put(key, intpGroup); + interpreterGroupWriteLock.unlock(); + } + try { + interpreterGroupReadLock.lock(); return interpreterGroupRef.get(key); + } finally { + interpreterGroupReadLock.unlock(); } } public Collection getAllInterpreterGroups() { - synchronized (interpreterGroupRef) { + try { + interpreterGroupReadLock.lock(); return new LinkedList<>(interpreterGroupRef.values()); + } finally { + interpreterGroupReadLock.unlock(); } } void closeAndRemoveInterpreterGroup(String noteId) { - String key = getInterpreterProcessKey(noteId); - InterpreterGroup groupToRemove; - synchronized (interpreterGroupRef) { - groupToRemove = interpreterGroupRef.remove(key); + String key = getInterpreterProcessKey("", noteId); + + InterpreterGroup groupToRemove = null; + for (String intpKey : new HashSet<>(interpreterGroupRef.keySet())) { + if (intpKey.contains(key)) { + interpreterGroupWriteLock.lock(); + groupToRemove = interpreterGroupRef.remove(intpKey); + interpreterGroupWriteLock.unlock(); + } } if (groupToRemove != null) { @@ -139,11 +168,9 @@ void closeAndRemoveInterpreterGroup(String noteId) { } void closeAndRmoveAllInterpreterGroups() { - synchronized (interpreterGroupRef) { - HashSet groupsToRemove = new HashSet<>(interpreterGroupRef.keySet()); - for (String key : groupsToRemove) { - closeAndRemoveInterpreterGroup(key); - } + HashSet groupsToRemove = new HashSet<>(interpreterGroupRef.keySet()); + for (String key : groupsToRemove) { + closeAndRemoveInterpreterGroup(key); } } diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java index 1281e71589d..7ad269701f5 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java @@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import com.google.common.base.Preconditions; import com.google.gson.Gson; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; @@ -286,8 +287,8 @@ public Paragraph insertParagraph(int index) { * @param paragraphId ID of paragraph * @return a paragraph that was deleted, or null otherwise */ - public Paragraph removeParagraph(String paragraphId) { - removeAllAngularObjectInParagraph(paragraphId); + public Paragraph removeParagraph(String user, String paragraphId) { + removeAllAngularObjectInParagraph(user, paragraphId); ResourcePoolUtils.removeResourcesBelongsToParagraph(getId(), paragraphId); synchronized (paragraphs) { Iterator i = paragraphs.iterator(); @@ -350,8 +351,8 @@ public void moveParagraph(String paragraphId, int index, boolean throwWhenIndexI if (index < 0 || index >= paragraphs.size()) { if (throwWhenIndexIsOutOfBound) { - throw new IndexOutOfBoundsException( - "paragraph size is " + paragraphs.size() + " , index is " + index); + throw new IndexOutOfBoundsException("paragraph size is " + paragraphs.size() + + " , index is " + index); } else { return; } @@ -437,6 +438,8 @@ private Map populateParagraphInfo(Paragraph p) { } if (p.getStatus().isRunning()) { info.put("progress", String.valueOf(p.progress())); + } else { + info.put("progress", String.valueOf(100)); } return info; } @@ -460,6 +463,9 @@ private void setParagraphMagic(Paragraph p, int index) { */ public void runAll() { String cronExecutingUser = (String) getConfig().get("cronExecutingUser"); + if (null == cronExecutingUser) { + cronExecutingUser = "anonymous"; + } synchronized (paragraphs) { for (Paragraph p : paragraphs) { if (!p.isEnabled()) { @@ -482,7 +488,8 @@ public void run(String paragraphId) { Paragraph p = getParagraph(paragraphId); p.setListener(jobListenerFactory.getParagraphJobListener(this)); String requiredReplName = p.getRequiredReplName(); - Interpreter intp = factory.getInterpreter(getId(), requiredReplName); + Interpreter intp = factory.getInterpreter(p.getUser(), getId(), requiredReplName); + if (intp == null) { String intpExceptionMsg = p.getJobName() + "'s Interpreter " + requiredReplName + " not found"; @@ -494,6 +501,7 @@ public void run(String paragraphId) { throw intpException; } if (p.getConfig().get("enabled") == null || (Boolean) p.getConfig().get("enabled")) { + p.setAuthenticationInfo(p.getAuthenticationInfo()); intp.getScheduler().submit(p); } } @@ -526,7 +534,7 @@ public List getParagraphs() { } } - private void snapshotAngularObjectRegistry() { + private void snapshotAngularObjectRegistry(String user) { angularObjects = new HashMap<>(); List settings = factory.getInterpreterSettings(getId()); @@ -535,13 +543,13 @@ private void snapshotAngularObjectRegistry() { } for (InterpreterSetting setting : settings) { - InterpreterGroup intpGroup = setting.getInterpreterGroup(id); + InterpreterGroup intpGroup = setting.getInterpreterGroup(user, id); AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry(); angularObjects.put(intpGroup.getId(), registry.getAllWithGlobal(id)); } } - private void removeAllAngularObjectInParagraph(String paragraphId) { + private void removeAllAngularObjectInParagraph(String user, String paragraphId) { angularObjects = new HashMap<>(); List settings = factory.getInterpreterSettings(getId()); @@ -550,7 +558,7 @@ private void removeAllAngularObjectInParagraph(String paragraphId) { } for (InterpreterSetting setting : settings) { - InterpreterGroup intpGroup = setting.getInterpreterGroup(id); + InterpreterGroup intpGroup = setting.getInterpreterGroup(user, id); AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry(); if (registry instanceof RemoteAngularObjectRegistry) { @@ -580,8 +588,9 @@ private void removeAllAngularObjectInParagraph(String paragraphId) { } public void persist(AuthenticationInfo subject) throws IOException { + Preconditions.checkNotNull(subject, "AuthenticationInfo should not be null"); stopDelayedPersistTimer(); - snapshotAngularObjectRegistry(); + snapshotAngularObjectRegistry(subject.getUser()); index.updateIndexDoc(this); repo.save(this, subject); } diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java index 1e65a86e21a..d996488cb61 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java @@ -31,6 +31,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; + +import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.collect.FluentIterable; import com.google.common.collect.Sets; @@ -135,6 +137,7 @@ public Notebook(ZeppelinConfiguration conf, NotebookRepo notebookRepo, * @throws IOException */ public Note createNote(AuthenticationInfo subject) throws IOException { + Preconditions.checkNotNull(subject, "AuthenticationInfo should not be null"); Note note; if (conf.getBoolean(ConfVars.ZEPPELIN_NOTEBOOK_AUTO_INTERPRETER_BINDING)) { note = createNote(replFactory.getDefaultInterpreterSettingList(), subject); @@ -158,7 +161,7 @@ public Note createNote(List interpreterIds, AuthenticationInfo subject) notes.put(note.getId(), note); } if (interpreterIds != null) { - bindInterpretersToNote(note.getId(), interpreterIds); + bindInterpretersToNote(subject.getUser(), note.getId(), interpreterIds); } if (subject != null && !"anonymous".equals(subject.getUser())) { @@ -252,7 +255,7 @@ public Note cloneNote(String sourceNoteID, String newNoteName, AuthenticationInf } // Copy the interpreter bindings List boundInterpreterSettingsIds = getBindedInterpreterSettingsIds(sourceNote.getId()); - bindInterpretersToNote(newNote.getId(), boundInterpreterSettingsIds); + bindInterpretersToNote(subject.getUser(), newNote.getId(), boundInterpreterSettingsIds); List paragraphs = sourceNote.getParagraphs(); for (Paragraph p : paragraphs) { @@ -264,7 +267,7 @@ public Note cloneNote(String sourceNoteID, String newNoteName, AuthenticationInf return newNote; } - public void bindInterpretersToNote(String id, List interpreterSettingIds) + public void bindInterpretersToNote(String user, String id, List interpreterSettingIds) throws IOException { Note note = getNote(id); if (note != null) { @@ -275,7 +278,7 @@ public void bindInterpretersToNote(String id, List interpreterSettingIds } } - replFactory.setInterpreters(note.getId(), interpreterSettingIds); + replFactory.setInterpreters(user, note.getId(), interpreterSettingIds); // comment out while note.getNoteReplLoader().setInterpreters(...) do the same // replFactory.putNoteInterpreterSettingBinding(id, interpreterSettingIds); } @@ -306,18 +309,21 @@ public Note getNote(String id) { } public void removeNote(String id, AuthenticationInfo subject) { + Preconditions.checkNotNull(subject, "AuthenticationInfo should not be null"); + Note note; synchronized (notes) { note = notes.remove(id); } - replFactory.removeNoteInterpreterSettingBinding(id); + replFactory.removeNoteInterpreterSettingBinding(subject.getUser(), id); notebookIndex.deleteIndexDocs(note); notebookAuthorization.removeNote(id); // remove from all interpreter instance's angular object registry for (InterpreterSetting settings : replFactory.get()) { - AngularObjectRegistry registry = settings.getInterpreterGroup(id).getAngularObjectRegistry(); + AngularObjectRegistry registry = + settings.getInterpreterGroup(subject.getUser(), id).getAngularObjectRegistry(); if (registry instanceof RemoteAngularObjectRegistry) { // remove paragraph scope object for (Paragraph p : note.getParagraphs()) { @@ -437,7 +443,7 @@ private Note loadNoteFromRepo(String id, AuthenticationInfo subject) { SnapshotAngularObject snapshot = angularObjectSnapshot.get(name); List settings = replFactory.get(); for (InterpreterSetting setting : settings) { - InterpreterGroup intpGroup = setting.getInterpreterGroup(note.getId()); + InterpreterGroup intpGroup = setting.getInterpreterGroup(subject.getUser(), note.getId()); if (intpGroup.getId().equals(snapshot.getIntpGroupId())) { AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry(); String noteId = snapshot.getAngularObject().getNoteId(); @@ -533,7 +539,7 @@ public int compare(Note note1, Note note2) { return noteList; } } - + public List getAllNotes(AuthenticationInfo subject) { final Set entities = Sets.newHashSet(); if (subject != null) { diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java index 7807abba416..955ba2dd00a 100644 --- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java +++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java @@ -105,6 +105,10 @@ private static String generateId() { + new Random(System.currentTimeMillis()).nextInt(); } + public String getUser() { + return user; + } + public String getText() { return text; } @@ -193,7 +197,7 @@ public static String getScriptBody(String text) { } public Interpreter getRepl(String name) { - return factory.getInterpreter(note.getId(), name); + return factory.getInterpreter(user, note.getId(), name); } public Interpreter getCurrentRepl() { @@ -442,8 +446,8 @@ private InterpreterContext getInterpreterContext(InterpreterOutput output) { if (!factory.getInterpreterSettings(note.getId()).isEmpty()) { InterpreterSetting intpGroup = factory.getInterpreterSettings(note.getId()).get(0); - registry = intpGroup.getInterpreterGroup(note.getId()).getAngularObjectRegistry(); - resourcePool = intpGroup.getInterpreterGroup(note.getId()).getResourcePool(); + registry = intpGroup.getInterpreterGroup(getUser(), note.getId()).getAngularObjectRegistry(); + resourcePool = intpGroup.getInterpreterGroup(getUser(), note.getId()).getResourcePool(); } List runners = new LinkedList(); @@ -582,6 +586,7 @@ public String getMagic() { } private boolean isValidInterpreter(String replName) { - return factory.getInterpreter(note.getId(), replName) != null; + return factory.getInterpreter("", + note.getId(), replName) != null; } } diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java index 29cdf554de6..294817c1908 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java @@ -27,6 +27,8 @@ import org.apache.zeppelin.scheduler.Job; import org.apache.zeppelin.scheduler.SchedulerFactory; import org.apache.zeppelin.search.SearchService; +import org.apache.zeppelin.user.AuthenticationInfo; +import org.apache.zeppelin.user.Credentials; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -50,6 +52,7 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory { private VFSNotebookRepo notebookRepo; private Notebook notebook; private HeliumApplicationFactory heliumAppFactory; + private AuthenticationInfo anonymous; @Before public void setUp() throws Exception { @@ -82,7 +85,7 @@ public void setUp() throws Exception { heliumAppFactory = new HeliumApplicationFactory(); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); factory = new InterpreterFactory(conf, - new InterpreterOption(true), null, null, heliumAppFactory, depResolver); + new InterpreterOption(true), null, null, heliumAppFactory, depResolver, false); HashMap env = new HashMap(); env.put("ZEPPELIN_CLASSPATH", new File("./target/test-classes").getAbsolutePath()); factory.setEnv(env); @@ -98,11 +101,13 @@ public void setUp() throws Exception { this, search, notebookAuthorization, - null); + new Credentials(false, null)); heliumAppFactory.setNotebook(notebook); notebook.addNotebookEventListener(heliumAppFactory); + + anonymous = new AuthenticationInfo("anonymous"); } @After @@ -131,13 +136,14 @@ public void testLoadRunUnloadApplication() HeliumTestApplication.class.getName(), new String[][]{}); - Note note1 = notebook.createNote(null); - factory.setInterpreters(note1.getId(),factory.getDefaultInterpreterSettingList()); + Note note1 = notebook.createNote(anonymous); + factory.setInterpreters("user", note1.getId(),factory.getDefaultInterpreterSettingList()); Paragraph p1 = note1.addParagraph(); // make sure interpreter process running p1.setText("%mock1 job"); + p1.setAuthenticationInfo(anonymous); note1.run(p1.getId()); while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); @@ -162,7 +168,7 @@ public void testLoadRunUnloadApplication() // clean heliumAppFactory.unload(p1, appId); - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Test @@ -175,13 +181,14 @@ public void testUnloadOnParagraphRemove() throws IOException { HeliumTestApplication.class.getName(), new String[][]{}); - Note note1 = notebook.createNote(null); - factory.setInterpreters(note1.getId(), factory.getDefaultInterpreterSettingList()); + Note note1 = notebook.createNote(anonymous); + factory.setInterpreters("user", note1.getId(), factory.getDefaultInterpreterSettingList()); Paragraph p1 = note1.addParagraph(); // make sure interpreter process running p1.setText("%mock1 job"); + p1.setAuthenticationInfo(anonymous); note1.run(p1.getId()); while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); @@ -193,13 +200,13 @@ public void testUnloadOnParagraphRemove() throws IOException { } // when remove paragraph - note1.removeParagraph(p1.getId()); + note1.removeParagraph("user", p1.getId()); // then assertEquals(ApplicationState.Status.UNLOADED, app.getStatus()); // clean - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @@ -213,13 +220,14 @@ public void testUnloadOnInterpreterUnbind() throws IOException { HeliumTestApplication.class.getName(), new String[][]{}); - Note note1 = notebook.createNote(null); - notebook.bindInterpretersToNote(note1.getId(), factory.getDefaultInterpreterSettingList()); + Note note1 = notebook.createNote(anonymous); + notebook.bindInterpretersToNote("user", note1.getId(), factory.getDefaultInterpreterSettingList()); Paragraph p1 = note1.addParagraph(); // make sure interpreter process running p1.setText("%mock1 job"); + p1.setAuthenticationInfo(anonymous); note1.run(p1.getId()); while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); @@ -231,19 +239,19 @@ public void testUnloadOnInterpreterUnbind() throws IOException { } // when unbind interpreter - notebook.bindInterpretersToNote(note1.getId(), new LinkedList()); + notebook.bindInterpretersToNote("user", note1.getId(), new LinkedList()); // then assertEquals(ApplicationState.Status.UNLOADED, app.getStatus()); // clean - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Test public void testInterpreterUnbindOfNullReplParagraph() throws IOException { // create note - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); // add paragraph with invalid magic Paragraph p1 = note1.addParagraph(); @@ -255,10 +263,10 @@ public void testInterpreterUnbindOfNullReplParagraph() throws IOException { // Unbind all interpreter from note // NullPointerException shouldn't occur here - notebook.bindInterpretersToNote(note1.getId(), new LinkedList()); + notebook.bindInterpretersToNote("user", note1.getId(), new LinkedList()); // remove note - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @@ -272,8 +280,8 @@ public void testUnloadOnInterpreterRestart() throws IOException { HeliumTestApplication.class.getName(), new String[][]{}); - Note note1 = notebook.createNote(null); - notebook.bindInterpretersToNote(note1.getId(), factory.getDefaultInterpreterSettingList()); + Note note1 = notebook.createNote(anonymous); + notebook.bindInterpretersToNote("user", note1.getId(), factory.getDefaultInterpreterSettingList()); String mock1IntpSettingId = null; for (InterpreterSetting setting : notebook.getBindedInterpreterSettings(note1.getId())) { if (setting.getName().equals("mock1")) { @@ -286,6 +294,7 @@ public void testUnloadOnInterpreterRestart() throws IOException { // make sure interpreter process running p1.setText("%mock1 job"); + p1.setAuthenticationInfo(anonymous); note1.run(p1.getId()); while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); assertEquals(0, p1.getAllApplicationStates().size()); @@ -307,7 +316,7 @@ public void testUnloadOnInterpreterRestart() throws IOException { assertEquals(ApplicationState.Status.UNLOADED, app.getStatus()); // clean - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Override diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java index 09031a59351..a2a799ae8a0 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java @@ -33,6 +33,8 @@ import org.apache.zeppelin.dep.DependencyResolver; import org.apache.zeppelin.interpreter.mock.MockInterpreter1; import org.apache.zeppelin.interpreter.mock.MockInterpreter2; +import org.apache.zeppelin.notebook.repo.zeppelinhub.security.Authentication; +import org.apache.zeppelin.user.AuthenticationInfo; import org.apache.zeppelin.interpreter.remote.RemoteInterpreter; import org.apache.zeppelin.notebook.JobListenerFactory; import org.apache.zeppelin.notebook.Note; @@ -87,7 +89,7 @@ public void setUp() throws Exception { conf = new ZeppelinConfiguration(); schedulerFactory = new SchedulerFactory(); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false); context = new InterpreterContext("note", "id", "title", "text", null, null, null, null, null, null, null); SearchService search = mock(SearchService.class); @@ -114,8 +116,8 @@ public void testBasic() { // mock1Setting = factory.createNewSetting("mock11", "mock1", new ArrayList(), new InterpreterOption(false), new Properties()); - InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("sharedProcess"); - factory.createInterpretersForNote(mock1Setting, "sharedProcess", "session"); + InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("user", "sharedProcess"); + factory.createInterpretersForNote(mock1Setting, "user", "sharedProcess", "session"); // get interpreter assertNotNull("get Interpreter", interpreterGroup.get("session").get(0)); @@ -125,12 +127,12 @@ public void testBasic() { // restart interpreter factory.restart(mock1Setting.getId()); - assertNull(mock1Setting.getInterpreterGroup("sharedProcess").get("session")); + assertNull(mock1Setting.getInterpreterGroup("user", "sharedProcess").get("session")); } @Test public void testRemoteRepl() throws Exception { - factory = new InterpreterFactory(conf, new InterpreterOption(true), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(true), null, null, null, depResolver, false); List all = factory.get(); InterpreterSetting mock1Setting = null; for (InterpreterSetting setting : all) { @@ -139,8 +141,8 @@ public void testRemoteRepl() throws Exception { break; } } - InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("sharedProcess"); - factory.createInterpretersForNote(mock1Setting, "sharedProcess", "session"); + InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("user", "sharedProcess"); + factory.createInterpretersForNote(mock1Setting, "user", "sharedProcess", "session"); // get interpreter assertNotNull("get Interpreter", interpreterGroup.get("session").get(0)); assertTrue(interpreterGroup.get("session").get(0) instanceof LazyOpenInterpreter); @@ -186,13 +188,13 @@ public void testSaveLoad() throws IOException, RepositoryException { factory.createNewSetting("new-mock1", "mock1", new LinkedList(), new InterpreterOption(false), new Properties()); assertEquals(numInterpreters + 1, factory.get().size()); - InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, null, depResolver); + InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, null, depResolver, false); assertEquals(numInterpreters + 1, factory2.get().size()); } @Test public void testInterpreterAliases() throws IOException, RepositoryException { - factory = new InterpreterFactory(conf, null, null, null, depResolver); + factory = new InterpreterFactory(conf, null, null, null, depResolver, false); final InterpreterInfo info1 = new InterpreterInfo("className1", "name1", true, null); final InterpreterInfo info2 = new InterpreterInfo("className2", "name1", true, null); factory.add("group1", new ArrayList(){{ @@ -205,15 +207,38 @@ public void testInterpreterAliases() throws IOException, RepositoryException { final InterpreterSetting setting1 = factory.createNewSetting("test-group1", "group1", new ArrayList(), new InterpreterOption(true), new Properties()); final InterpreterSetting setting2 = factory.createNewSetting("test-group2", "group1", new ArrayList(), new InterpreterOption(true), new Properties()); - factory.setInterpreters("note", new ArrayList() {{ + factory.setInterpreters("user", "note", new ArrayList() {{ add(setting1.getId()); add(setting2.getId()); }}); - assertEquals("className1", factory.getInterpreter("note", "test-group1").getClassName()); - assertEquals("className1", factory.getInterpreter("note", "group1").getClassName()); + assertEquals("className1", factory.getInterpreter("user1", "note", "test-group1").getClassName()); + assertEquals("className1", factory.getInterpreter("user1", "note", "group1").getClassName()); } + @Test + public void testMultiUser() throws IOException, RepositoryException { + factory = new InterpreterFactory(conf, null, null, null, depResolver, true); + final InterpreterInfo info1 = new InterpreterInfo("className1", "name1", true, null); + factory.add("group1", new ArrayList(){{ + add(info1); + }}, new ArrayList(), new InterpreterOption(true), new Properties(), "/path1"); + + InterpreterOption perUserInterpreterOption = new InterpreterOption(true, InterpreterOption.ISOLATED, InterpreterOption.SHARED); + final InterpreterSetting setting1 = factory.createNewSetting("test-group1", "group1", new ArrayList(), perUserInterpreterOption, new Properties()); + + factory.setInterpreters("user1", "note", new ArrayList() {{ + add(setting1.getId()); + }}); + + factory.setInterpreters("user2", "note", new ArrayList() {{ + add(setting1.getId()); + }}); + + assertNotEquals(factory.getInterpreter("user1", "note", "test-group1"), factory.getInterpreter("user2", "note", "test-group1")); + } + + @Test public void testInvalidInterpreterSettingName() { try { @@ -233,19 +258,19 @@ public void getEditorSetting() throws IOException, RepositoryException, Schedule intpIds.add(intpSetting.getId()); } } - Note note = notebook.createNote(intpIds, null); + Note note = notebook.createNote(intpIds, new AuthenticationInfo("anonymous")); // get editor setting from interpreter-setting.json - Map editor = factory.getEditorSetting(note.getId(), "mock11"); + Map editor = factory.getEditorSetting("user1", note.getId(), "mock11"); assertEquals("java", editor.get("language")); // when interpreter is not loaded via interpreter-setting.json // or editor setting doesn't exit - editor = factory.getEditorSetting(note.getId(), "mock1"); + editor = factory.getEditorSetting("user1", note.getId(), "mock1"); assertEquals(null, editor.get("language")); // when interpreter is not bound to note - editor = factory.getEditorSetting(note.getId(), "mock2"); + editor = factory.getEditorSetting("user1", note.getId(), "mock2"); assertEquals("text", editor.get("language")); } } diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java index 245089963ea..d19ceae08e4 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java @@ -60,7 +60,7 @@ public void setUp() throws Exception { MockInterpreter2.register("mock2", "group2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2"); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false); } @After @@ -71,92 +71,92 @@ public void tearDown() throws Exception { @Test public void testGetInterpreter() throws IOException { - factory.setInterpreters("note", factory.getDefaultInterpreterSettingList()); + factory.setInterpreters("user", "note", factory.getDefaultInterpreterSettingList()); // when there're no interpreter selection directive - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", null).getClassName()); - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", "").getClassName()); - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", " ").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", null).getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", "").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", " ").getClassName()); // when group name is omitted - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("note", "mock11").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("user", "note", "mock11").getClassName()); // when 'name' is ommitted - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", "group1").getClassName()); - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("note", "group2").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", "group1").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("user", "note", "group2").getClassName()); // when nothing is ommitted - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", "group1.mock1").getClassName()); - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("note", "group1.mock11").getClassName()); - assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("note", "group2.mock2").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", "group1.mock1").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("user", "note", "group1.mock11").getClassName()); + assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("user", "note", "group2.mock2").getClassName()); - factory.closeNote("note"); + factory.closeNote("user", "note"); } @Test public void testNoteSession() throws IOException { - factory.setInterpreters("noteA", factory.getDefaultInterpreterSettingList()); - factory.getInterpreterSettings("noteA").get(0).getOption().setPerNoteSession(true); + factory.setInterpreters("user", "noteA", factory.getDefaultInterpreterSettingList()); + factory.getInterpreterSettings("noteA").get(0).getOption().setPerNote(InterpreterOption.SCOPED); - factory.setInterpreters("noteB", factory.getDefaultInterpreterSettingList()); - factory.getInterpreterSettings("noteB").get(0).getOption().setPerNoteSession(true); + factory.setInterpreters("user", "noteB", factory.getDefaultInterpreterSettingList()); + factory.getInterpreterSettings("noteB").get(0).getOption().setPerNote(InterpreterOption.SCOPED); // interpreters are not created before accessing it - assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("shared_process").get("noteA")); - assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("shared_process").get("noteB")); + assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA")); + assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB")); - factory.getInterpreter("noteA", null).open(); - factory.getInterpreter("noteB", null).open(); + factory.getInterpreter("user", "noteA", null).open(); + factory.getInterpreter("user", "noteB", null).open(); assertTrue( - factory.getInterpreter("noteA", null).getInterpreterGroup().getId().equals( - factory.getInterpreter("noteB", null).getInterpreterGroup().getId())); + factory.getInterpreter("user", "noteA", null).getInterpreterGroup().getId().equals( + factory.getInterpreter("user", "noteB", null).getInterpreterGroup().getId())); // interpreters are created after accessing it - assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("shared_process").get("noteA")); - assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("shared_process").get("noteB")); + assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA")); + assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB")); // when - factory.closeNote("noteA"); - factory.closeNote("noteB"); + factory.closeNote("user", "noteA"); + factory.closeNote("user", "noteB"); // interpreters are destroyed after close - assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("shared_process").get("noteA")); - assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("shared_process").get("noteB")); + assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "shared_process").get("noteA")); + assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "shared_process").get("noteB")); } @Test public void testNotePerInterpreterProcess() throws IOException { - factory.setInterpreters("noteA", factory.getDefaultInterpreterSettingList()); - factory.getInterpreterSettings("noteA").get(0).getOption().setPerNoteProcess(true); + factory.setInterpreters("user", "noteA", factory.getDefaultInterpreterSettingList()); + factory.getInterpreterSettings("noteA").get(0).getOption().setPerNote(InterpreterOption.ISOLATED); - factory.setInterpreters("noteB", factory.getDefaultInterpreterSettingList()); - factory.getInterpreterSettings("noteB").get(0).getOption().setPerNoteProcess(true); + factory.setInterpreters("user", "noteB", factory.getDefaultInterpreterSettingList()); + factory.getInterpreterSettings("noteB").get(0).getOption().setPerNote(InterpreterOption.ISOLATED); // interpreters are not created before accessing it - assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("noteA").get("noteA")); - assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("noteB").get("noteB")); + assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA")); + assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB")); - factory.getInterpreter("noteA", null).open(); - factory.getInterpreter("noteB", null).open(); + factory.getInterpreter("user", "noteA", null).open(); + factory.getInterpreter("user", "noteB", null).open(); // per note interpreter process assertFalse( - factory.getInterpreter("noteA", null).getInterpreterGroup().getId().equals( - factory.getInterpreter("noteB", null).getInterpreterGroup().getId())); + factory.getInterpreter("user", "noteA", null).getInterpreterGroup().getId().equals( + factory.getInterpreter("user", "noteB", null).getInterpreterGroup().getId())); // interpreters are created after accessing it - assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("noteA").get("noteA")); - assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("noteB").get("noteB")); + assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA")); + assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB")); // when - factory.closeNote("noteA"); - factory.closeNote("noteB"); + factory.closeNote("user", "noteA"); + factory.closeNote("user", "noteB"); // interpreters are destroyed after close - assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("noteA").get("noteA")); - assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("noteB").get("noteB")); + assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA")); + assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB")); } diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java index a44bfad478a..a07727458f2 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java @@ -22,6 +22,7 @@ import org.apache.zeppelin.notebook.repo.NotebookRepo; import org.apache.zeppelin.scheduler.Scheduler; import org.apache.zeppelin.search.SearchService; +import org.apache.zeppelin.user.AuthenticationInfo; import org.apache.zeppelin.user.Credentials; import org.junit.Test; import org.junit.runner.RunWith; @@ -58,9 +59,11 @@ public class NoteTest { @Mock InterpreterFactory interpreterFactory; + private AuthenticationInfo anonymous = new AuthenticationInfo("anonymous"); + @Test public void runNormalTest() { - when(interpreterFactory.getInterpreter(anyString(), eq("spark"))).thenReturn(interpreter); + when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("spark"))).thenReturn(interpreter); when(interpreter.getScheduler()).thenReturn(scheduler); String pText = "%spark sc.version"; @@ -68,11 +71,12 @@ public void runNormalTest() { Paragraph p = note.addParagraph(); p.setText(pText); + p.setAuthenticationInfo(anonymous); note.run(p.getId()); ArgumentCaptor pCaptor = ArgumentCaptor.forClass(Paragraph.class); verify(scheduler, only()).submit(pCaptor.capture()); - verify(interpreterFactory, only()).getInterpreter(anyString(), eq("spark")); + verify(interpreterFactory, only()).getInterpreter(anyString(), anyString(), eq("spark")); assertEquals("Paragraph text", pText, pCaptor.getValue().getText()); } @@ -87,7 +91,7 @@ public void addParagraphWithEmptyReplNameTest() { @Test public void addParagraphWithLastReplNameTest() { - when(interpreterFactory.getInterpreter(anyString(), eq("spark"))).thenReturn(interpreter); + when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("spark"))).thenReturn(interpreter); Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener); Paragraph p1 = note.addParagraph(); @@ -99,7 +103,7 @@ public void addParagraphWithLastReplNameTest() { @Test public void insertParagraphWithLastReplNameTest() { - when(interpreterFactory.getInterpreter(anyString(), eq("spark"))).thenReturn(interpreter); + when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("spark"))).thenReturn(interpreter); Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener); Paragraph p1 = note.addParagraph(); @@ -111,7 +115,7 @@ public void insertParagraphWithLastReplNameTest() { @Test public void insertParagraphWithInvalidReplNameTest() { - when(interpreterFactory.getInterpreter(anyString(), eq("invalid"))).thenReturn(null); + when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("invalid"))).thenReturn(null); Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener); Paragraph p1 = note.addParagraph(); diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java index 86d6c06f55f..d0af2c90abe 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java @@ -65,6 +65,7 @@ public class NotebookTest implements JobListenerFactory{ private DependencyResolver depResolver; private NotebookAuthorization notebookAuthorization; private Credentials credentials; + private AuthenticationInfo anonymous = new AuthenticationInfo("anonymous"); @Before public void setUp() throws Exception { @@ -88,7 +89,7 @@ public void setUp() throws Exception { MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2"); depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false); SearchService search = mock(SearchService.class); notebookRepo = new VFSNotebookRepo(conf); @@ -106,8 +107,8 @@ public void tearDown() throws Exception { @Test public void testSelectingReplImplementation() throws IOException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); // run with default repl Paragraph p1 = note.addParagraph(); @@ -115,6 +116,7 @@ public void testSelectingReplImplementation() throws IOException { config.put("enabled", true); p1.setConfig(config); p1.setText("hello world"); + p1.setAuthenticationInfo(anonymous); note.run(p1.getId()); while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield(); assertEquals("repl1: hello world", p1.getResult().message()); @@ -123,10 +125,11 @@ public void testSelectingReplImplementation() throws IOException { Paragraph p2 = note.addParagraph(); p2.setConfig(config); p2.setText("%mock2 hello world"); + p2.setAuthenticationInfo(anonymous); note.run(p2.getId()); while(p2.isTerminated()==false || p2.getResult()==null) Thread.yield(); assertEquals("repl2: hello world", p2.getResult().message()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test @@ -137,7 +140,7 @@ public void testReloadAndSetInterpreter() throws IOException { FileUtils.copyDirectory(srcDir, destDir); // when load - notebook.reloadAllNotes(null); + notebook.reloadAllNotes(anonymous); assertEquals(1, notebook.getAllNotes().size()); // then interpreter factory should be injected into all the paragraphs @@ -169,8 +172,8 @@ public void testReloadAllNotes() throws IOException { assertEquals(notes.size(), 0); // load copied notebook on memory when reloadAllNotes() is called - Note copiedNote = notebookRepo.get("2A94M5J1Z", null); - notebook.reloadAllNotes(null); + Note copiedNote = notebookRepo.get("2A94M5J1Z", anonymous); + notebook.reloadAllNotes(anonymous); notes = notebook.getAllNotes(); assertEquals(notes.size(), 2); assertEquals(notes.get(1).getId(), copiedNote.getId()); @@ -188,14 +191,14 @@ public void testReloadAllNotes() throws IOException { assertEquals(notes.size(), 2); // delete notebook from notebook list when reloadAllNotes() is called - notebook.reloadAllNotes(null); + notebook.reloadAllNotes(anonymous); notes = notebook.getAllNotes(); assertEquals(notes.size(), 0); } @Test public void testPersist() throws IOException, SchedulerException, RepositoryException { - Note note = notebook.createNote(null); + Note note = notebook.createNote(anonymous); // run with default repl Paragraph p1 = note.addParagraph(); @@ -203,14 +206,14 @@ public void testPersist() throws IOException, SchedulerException, RepositoryExce config.put("enabled", true); p1.setConfig(config); p1.setText("hello world"); - note.persist(null); + note.persist(anonymous); Notebook notebook2 = new Notebook( conf, notebookRepo, schedulerFactory, - new InterpreterFactory(conf, null, null, null, depResolver), this, null, null, null); + new InterpreterFactory(conf, null, null, null, depResolver, false), this, null, null, null); assertEquals(1, notebook2.getAllNotes().size()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test @@ -223,17 +226,18 @@ public void testCreateNoteWithSubject() throws IOException, SchedulerException, Set owners = new HashSet<>(); owners.add("user1"); assertEquals(owners, notebook.getNotebookAuthorization().getOwners(note.getId())); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testClearParagraphOutput() throws IOException, SchedulerException{ - Note note = notebook.createNote(null); + Note note = notebook.createNote(anonymous); Paragraph p1 = note.addParagraph(); Map config = p1.getConfig(); config.put("enabled", true); p1.setConfig(config); p1.setText("hello world"); + p1.setAuthenticationInfo(anonymous); note.run(p1.getId()); while(p1.isTerminated() == false || p1.getResult() == null) Thread.yield(); @@ -242,13 +246,13 @@ public void testClearParagraphOutput() throws IOException, SchedulerException{ // clear paragraph output/result note.clearParagraphOutput(p1.getId()); assertNull(p1.getResult()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testRunAll() throws IOException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters("user", note.getId(), factory.getDefaultInterpreterSettingList()); // p1 Paragraph p1 = note.addParagraph(); @@ -280,14 +284,14 @@ public void testRunAll() throws IOException { assertNull(p2.getResult()); assertEquals("repl1: p3", p3.getResult().message()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testSchedule() throws InterruptedException, IOException { // create a note and a paragraph - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters("user", note.getId(), factory.getDefaultInterpreterSettingList()); Paragraph p = note.addParagraph(); Map config = new HashMap(); @@ -313,14 +317,14 @@ public void testSchedule() throws InterruptedException, IOException { assertNotNull(dateFinished); Thread.sleep(1 * 1000); assertEquals(dateFinished, p.getDateFinished()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testAutoRestartInterpreterAfterSchedule() throws InterruptedException, IOException{ // create a note and a paragraph - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); Paragraph p = note.addParagraph(); Map config = new HashMap(); @@ -341,11 +345,11 @@ public void testAutoRestartInterpreterAfterSchedule() throws InterruptedExceptio MockInterpreter1 mock1 = ((MockInterpreter1) (((ClassloaderInterpreter) - ((LazyOpenInterpreter) factory.getInterpreter(note.getId(), "mock1")).getInnerInterpreter()) + ((LazyOpenInterpreter) factory.getInterpreter(anonymous.getUser(), note.getId(), "mock1")).getInnerInterpreter()) .getInnerInterpreter())); MockInterpreter2 mock2 = ((MockInterpreter2) (((ClassloaderInterpreter) - ((LazyOpenInterpreter) factory.getInterpreter(note.getId(), "mock2")).getInnerInterpreter()) + ((LazyOpenInterpreter) factory.getInterpreter(anonymous.getUser(), note.getId(), "mock2")).getInnerInterpreter()) .getInnerInterpreter())); // wait until interpreters are started @@ -366,14 +370,14 @@ public void testAutoRestartInterpreterAfterSchedule() throws InterruptedExceptio // make sure all paragraph has been executed assertNotNull(p.getDateFinished()); assertNotNull(p2.getDateFinished()); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testExportAndImportNote() throws IOException, CloneNotSupportedException, InterruptedException, InterpreterException, SchedulerException, RepositoryException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters("user", note.getId(), factory.getDefaultInterpreterSettingList()); final Paragraph p = note.addParagraph(); String simpleText = "hello world"; @@ -386,7 +390,7 @@ public void testExportAndImportNote() throws IOException, CloneNotSupportedExcep String exportedNoteJson = notebook.exportNote(note.getId()); - Note importedNote = notebook.importNote(exportedNoteJson, "Title", null); + Note importedNote = notebook.importNote(exportedNoteJson, "Title", anonymous); Paragraph p2 = importedNote.getParagraphs().get(0); @@ -403,16 +407,16 @@ public void testExportAndImportNote() throws IOException, CloneNotSupportedExcep Set owners = new HashSet<>(); owners.add("user1"); assertEquals(owners, notebook.getNotebookAuthorization().getOwners(importedNote2.getId())); - notebook.removeNote(note.getId(), null); - notebook.removeNote(importedNote.getId(), null); - notebook.removeNote(importedNote2.getId(), null); + notebook.removeNote(note.getId(), anonymous); + notebook.removeNote(importedNote.getId(), anonymous); + notebook.removeNote(importedNote2.getId(), anonymous); } @Test public void testCloneNote() throws IOException, CloneNotSupportedException, InterruptedException, InterpreterException, SchedulerException, RepositoryException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters("user", note.getId(), factory.getDefaultInterpreterSettingList()); final Paragraph p = note.addParagraph(); p.setText("hello world"); @@ -420,7 +424,7 @@ public void testCloneNote() throws IOException, CloneNotSupportedException, while(p.isTerminated()==false || p.getResult()==null) Thread.yield(); p.setStatus(Status.RUNNING); - Note cloneNote = notebook.cloneNote(note.getId(), "clone note", null); + Note cloneNote = notebook.cloneNote(note.getId(), "clone note", anonymous); Paragraph cp = cloneNote.paragraphs.get(0); assertEquals(cp.getStatus(), Status.READY); @@ -437,28 +441,28 @@ public void testCloneNote() throws IOException, CloneNotSupportedException, Set owners = new HashSet<>(); owners.add("user1"); assertEquals(owners, notebook.getNotebookAuthorization().getOwners(cloneNote2.getId())); - notebook.removeNote(note.getId(), null); - notebook.removeNote(cloneNote.getId(), null); - notebook.removeNote(cloneNote2.getId(), null); + notebook.removeNote(note.getId(), anonymous); + notebook.removeNote(cloneNote.getId(), anonymous); + notebook.removeNote(cloneNote2.getId(), anonymous); } @Test public void testCloneNoteWithNoName() throws IOException, CloneNotSupportedException, InterruptedException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); - Note cloneNote = notebook.cloneNote(note.getId(), null, null); + Note cloneNote = notebook.cloneNote(note.getId(), null, anonymous); assertEquals(cloneNote.getName(), "Note " + cloneNote.getId()); - notebook.removeNote(note.getId(), null); - notebook.removeNote(cloneNote.getId(), null); + notebook.removeNote(note.getId(), anonymous); + notebook.removeNote(cloneNote.getId(), anonymous); } @Test public void testCloneNoteWithExceptionResult() throws IOException, CloneNotSupportedException, InterruptedException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); final Paragraph p = note.addParagraph(); p.setText("hello world"); @@ -469,21 +473,21 @@ public void testCloneNoteWithExceptionResult() throws IOException, CloneNotSuppo // Force paragraph to have String type object p.setResult("Exception"); - Note cloneNote = notebook.cloneNote(note.getId(), "clone note with Exception result", null); + Note cloneNote = notebook.cloneNote(note.getId(), "clone note with Exception result", anonymous); Paragraph cp = cloneNote.paragraphs.get(0); // Keep same ParagraphID assertEquals(cp.getId(), p.getId()); assertEquals(cp.text, p.text); assertNull(cp.getResult()); - notebook.removeNote(note.getId(), null); - notebook.removeNote(cloneNote.getId(), null); + notebook.removeNote(note.getId(), anonymous); + notebook.removeNote(cloneNote.getId(), anonymous); } @Test public void testResourceRemovealOnParagraphNoteRemove() throws IOException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); for (InterpreterGroup intpGroup : InterpreterGroup.getAll()) { intpGroup.setResourcePool(new LocalResourcePool(intpGroup.getId())); } @@ -499,11 +503,11 @@ public void testResourceRemovealOnParagraphNoteRemove() throws IOException { assertEquals(2, ResourcePoolUtils.getAllResources().size()); // remove a paragraph - note.removeParagraph(p1.getId()); + note.removeParagraph(anonymous.getUser(), p1.getId()); assertEquals(1, ResourcePoolUtils.getAllResources().size()); // remove note - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); assertEquals(0, ResourcePoolUtils.getAllResources().size()); } @@ -511,11 +515,11 @@ public void testResourceRemovealOnParagraphNoteRemove() throws IOException { public void testAngularObjectRemovalOnNotebookRemove() throws InterruptedException, IOException { // create a note and a paragraph - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); AngularObjectRegistry registry = factory - .getInterpreterSettings(note.getId()).get(0).getInterpreterGroup("sharedProcess") + .getInterpreterSettings(note.getId()).get(0).getInterpreterGroup(anonymous.getUser(), "sharedProcess") .getAngularObjectRegistry(); Paragraph p1 = note.addParagraph(); @@ -530,7 +534,7 @@ public void testAngularObjectRemovalOnNotebookRemove() throws InterruptedExcepti registry.add("o3", "object3", null, null); // remove notebook - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); // notebook scope or paragraph scope object should be removed assertNull(registry.get("o1", note.getId(), null)); @@ -544,11 +548,11 @@ public void testAngularObjectRemovalOnNotebookRemove() throws InterruptedExcepti public void testAngularObjectRemovalOnParagraphRemove() throws InterruptedException, IOException { // create a note and a paragraph - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); AngularObjectRegistry registry = factory - .getInterpreterSettings(note.getId()).get(0).getInterpreterGroup("sharedProcess") + .getInterpreterSettings(note.getId()).get(0).getInterpreterGroup(anonymous.getUser(), "sharedProcess") .getAngularObjectRegistry(); Paragraph p1 = note.addParagraph(); @@ -563,7 +567,7 @@ public void testAngularObjectRemovalOnParagraphRemove() throws InterruptedExcept registry.add("o3", "object3", null, null); // remove notebook - note.removeParagraph(p1.getId()); + note.removeParagraph(anonymous.getUser(), p1.getId()); // paragraph scope should be removed assertNull(registry.get("o1", note.getId(), null)); @@ -571,18 +575,18 @@ public void testAngularObjectRemovalOnParagraphRemove() throws InterruptedExcept // notebook scope and global object sould be remained assertNotNull(registry.get("o2", note.getId(), null)); assertNotNull(registry.get("o3", null, null)); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testAngularObjectRemovalOnInterpreterRestart() throws InterruptedException, IOException { // create a note and a paragraph - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); AngularObjectRegistry registry = factory - .getInterpreterSettings(note.getId()).get(0).getInterpreterGroup("sharedProcess") + .getInterpreterSettings(note.getId()).get(0).getInterpreterGroup(anonymous.getUser(), "sharedProcess") .getAngularObjectRegistry(); // add local scope object @@ -592,19 +596,19 @@ public void testAngularObjectRemovalOnInterpreterRestart() throws InterruptedExc // restart interpreter factory.restart(factory.getInterpreterSettings(note.getId()).get(0).getId()); - registry = factory.getInterpreterSettings(note.getId()).get(0).getInterpreterGroup("sharedProcess") + registry = factory.getInterpreterSettings(note.getId()).get(0).getInterpreterGroup(anonymous.getUser(), "sharedProcess") .getAngularObjectRegistry(); // local and global scope object should be removed assertNull(registry.get("o1", note.getId(), null)); assertNull(registry.get("o2", null, null)); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testPermissions() throws IOException { // create a note and a paragraph - Note note = notebook.createNote(null); + Note note = notebook.createNote(anonymous); NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization(); // empty owners, readers or writers means note is public assertEquals(notebookAuthorization.isOwner(note.getId(), @@ -643,14 +647,14 @@ public void testPermissions() throws IOException { assertEquals(notebookAuthorization.isReader(note.getId(), new HashSet(Arrays.asList("user3"))), true); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testAbortParagraphStatusOnInterpreterRestart() throws InterruptedException, IOException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + Note note = notebook.createNote(anonymous); + factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList()); ArrayList paragraphs = new ArrayList<>(); for (int i = 0; i < 100; i++) { @@ -681,19 +685,20 @@ public void testAbortParagraphStatusOnInterpreterRestart() throws InterruptedExc } assertTrue(isAborted); - notebook.removeNote(note.getId(), null); + notebook.removeNote(note.getId(), anonymous); } @Test public void testPerSessionInterpreterCloseOnNoteRemoval() throws IOException { // create a notes - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); Paragraph p1 = note1.addParagraph(); p1.setText("getId"); + p1.setAuthenticationInfo(anonymous); - // restart interpreter with per note session enabled + // restart interpreter with per user session enabled for (InterpreterSetting setting : factory.getInterpreterSettings(note1.getId())) { - setting.getOption().setPerNoteSession(true); + setting.getOption().setPerNote(setting.getOption().SCOPED); notebook.getInterpreterFactory().restart(setting.getId()); } @@ -702,29 +707,32 @@ public void testPerSessionInterpreterCloseOnNoteRemoval() throws IOException { InterpreterResult result = p1.getResult(); // remove note and recreate - notebook.removeNote(note1.getId(), null); - note1 = notebook.createNote(null); + notebook.removeNote(note1.getId(), anonymous); + note1 = notebook.createNote(anonymous); p1 = note1.addParagraph(); p1.setText("getId"); + p1.setAuthenticationInfo(anonymous); note1.run(p1.getId()); while (p1.getStatus() != Status.FINISHED) Thread.yield(); assertNotEquals(p1.getResult().message(), result.message()); - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Test public void testPerSessionInterpreter() throws IOException { // create two notes - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); Paragraph p1 = note1.addParagraph(); - Note note2 = notebook.createNote(null); + Note note2 = notebook.createNote(anonymous); Paragraph p2 = note2.addParagraph(); p1.setText("getId"); + p1.setAuthenticationInfo(anonymous); p2.setText("getId"); + p2.setAuthenticationInfo(anonymous); // run per note session disabled note1.run(p1.getId()); @@ -738,7 +746,7 @@ public void testPerSessionInterpreter() throws IOException { // restart interpreter with per note session enabled for (InterpreterSetting setting : notebook.getInterpreterFactory().getInterpreterSettings(note1.getId())) { - setting.getOption().setPerNoteSession(true); + setting.getOption().setPerNote(InterpreterOption.SCOPED); notebook.getInterpreterFactory().restart(setting.getId()); } @@ -751,20 +759,21 @@ public void testPerSessionInterpreter() throws IOException { assertNotEquals(p1.getResult().message(), p2.getResult().message()); - notebook.removeNote(note1.getId(), null); - notebook.removeNote(note2.getId(), null); + notebook.removeNote(note1.getId(), anonymous); + notebook.removeNote(note2.getId(), anonymous); } @Test public void testPerSessionInterpreterCloseOnUnbindInterpreterSetting() throws IOException { // create a notes - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); Paragraph p1 = note1.addParagraph(); + p1.setAuthenticationInfo(anonymous); p1.setText("getId"); // restart interpreter with per note session enabled for (InterpreterSetting setting : factory.getInterpreterSettings(note1.getId())) { - setting.getOption().setPerNoteSession(true); + setting.getOption().setPerNote(InterpreterOption.SCOPED); notebook.getInterpreterFactory().restart(setting.getId()); } @@ -775,15 +784,15 @@ public void testPerSessionInterpreterCloseOnUnbindInterpreterSetting() throws IO // unbind, and rebind setting. that result interpreter instance close List bindedSettings = notebook.getBindedInterpreterSettingsIds(note1.getId()); - notebook.bindInterpretersToNote(note1.getId(), new LinkedList()); - notebook.bindInterpretersToNote(note1.getId(), bindedSettings); + notebook.bindInterpretersToNote(anonymous.getUser(), note1.getId(), new LinkedList()); + notebook.bindInterpretersToNote(anonymous.getUser(), note1.getId(), bindedSettings); note1.run(p1.getId()); while (p1.getStatus() != Status.FINISHED) Thread.yield(); assertNotEquals(result.message(), p1.getResult().message()); - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Test @@ -825,7 +834,7 @@ public void onParagraphStatusChange(Paragraph p, Status status) { } }); - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); assertEquals(1, onNoteCreate.get()); Paragraph p1 = note1.addParagraph(); @@ -834,14 +843,14 @@ public void onParagraphStatusChange(Paragraph p, Status status) { note1.addCloneParagraph(p1); assertEquals(2, onParagraphCreate.get()); - note1.removeParagraph(p1.getId()); + note1.removeParagraph(anonymous.getUser(), p1.getId()); assertEquals(1, onParagraphRemove.get()); List settings = notebook.getBindedInterpreterSettingsIds(note1.getId()); - notebook.bindInterpretersToNote(note1.getId(), new LinkedList()); + notebook.bindInterpretersToNote(anonymous.getUser(), note1.getId(), new LinkedList()); assertEquals(settings.size(), unbindInterpreter.get()); - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); assertEquals(1, onNoteRemove.get()); assertEquals(1, onParagraphRemove.get()); } @@ -849,7 +858,7 @@ public void onParagraphStatusChange(Paragraph p, Status status) { @Test public void testNormalizeNoteName() throws IOException { // create a notes - Note note1 = notebook.createNote(null); + Note note1 = notebook.createNote(anonymous); note1.setName("MyNote"); assertEquals(note1.getName(), "MyNote"); @@ -869,29 +878,29 @@ public void testNormalizeNoteName() throws IOException { note1.setName("\\\\\\MyNote///sub"); assertEquals(note1.getName(), "/MyNote/sub"); - notebook.removeNote(note1.getId(), null); + notebook.removeNote(note1.getId(), anonymous); } @Test public void testGetAllNotes() throws Exception { - Note note1 = notebook.createNote(null); - Note note2 = notebook.createNote(null); - assertEquals(2, notebook.getAllNotes(new AuthenticationInfo("anonymous")).size()); + Note note1 = notebook.createNote(anonymous); + Note note2 = notebook.createNote(anonymous); + assertEquals(2, notebook.getAllNotes(anonymous).size()); notebook.getNotebookAuthorization().setOwners(note1.getId(), Sets.newHashSet("user1")); notebook.getNotebookAuthorization().setWriters(note1.getId(), Sets.newHashSet("user1")); notebook.getNotebookAuthorization().setReaders(note1.getId(), Sets.newHashSet("user1")); - assertEquals(1, notebook.getAllNotes(new AuthenticationInfo("anonymous")).size()); + assertEquals(1, notebook.getAllNotes(anonymous).size()); assertEquals(2, notebook.getAllNotes(new AuthenticationInfo("user1")).size()); notebook.getNotebookAuthorization().setOwners(note2.getId(), Sets.newHashSet("user2")); notebook.getNotebookAuthorization().setWriters(note2.getId(), Sets.newHashSet("user2")); notebook.getNotebookAuthorization().setReaders(note2.getId(), Sets.newHashSet("user2")); - assertEquals(0, notebook.getAllNotes(new AuthenticationInfo("anonymous")).size()); + assertEquals(0, notebook.getAllNotes(anonymous).size()); assertEquals(1, notebook.getAllNotes(new AuthenticationInfo("user1")).size()); assertEquals(1, notebook.getAllNotes(new AuthenticationInfo("user2")).size()); - notebook.removeNote(note1.getId(), null); - notebook.removeNote(note2.getId(), null); + notebook.removeNote(note1.getId(), anonymous); + notebook.removeNote(note2.getId(), anonymous); } diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java index 5a3915cc6f5..43ed586135e 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java @@ -42,6 +42,7 @@ import org.apache.zeppelin.scheduler.SchedulerFactory; import org.apache.zeppelin.search.SearchService; import org.apache.zeppelin.search.LuceneSearch; +import org.apache.zeppelin.user.AuthenticationInfo; import org.apache.zeppelin.user.Credentials; import org.junit.After; import org.junit.Before; @@ -65,6 +66,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory { private SearchService search; private NotebookAuthorization notebookAuthorization; private Credentials credentials; + private AuthenticationInfo anonymous; private static final Logger LOG = LoggerFactory.getLogger(NotebookRepoSyncTest.class); @Before @@ -95,7 +97,7 @@ public void setUp() throws Exception { MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2"); depResolver = new DependencyResolver(mainZepDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false); search = mock(SearchService.class); notebookRepoSync = new NotebookRepoSync(conf); @@ -103,6 +105,7 @@ public void setUp() throws Exception { credentials = new Credentials(conf.credentialsPersist(), conf.getCredentialsPath()); notebookSync = new Notebook(conf, notebookRepoSync, schedulerFactory, factory, this, search, notebookAuthorization, credentials); + anonymous = new AuthenticationInfo("anonymous"); } @After @@ -119,40 +122,40 @@ public void testRepoCount() throws IOException { public void testSyncOnCreate() throws IOException { /* check that both storage systems are empty */ assertTrue(notebookRepoSync.getRepoCount() > 1); - assertEquals(0, notebookRepoSync.list(0, null).size()); - assertEquals(0, notebookRepoSync.list(1, null).size()); + assertEquals(0, notebookRepoSync.list(0, anonymous).size()); + assertEquals(0, notebookRepoSync.list(1, anonymous).size()); /* create note */ - Note note = notebookSync.createNote(null); + Note note = notebookSync.createNote(anonymous); // check that automatically saved on both storages - assertEquals(1, notebookRepoSync.list(0, null).size()); - assertEquals(1, notebookRepoSync.list(1, null).size()); - assertEquals(notebookRepoSync.list(0, null).get(0).getId(),notebookRepoSync.list(1, null).get(0).getId()); - - notebookSync.removeNote(notebookRepoSync.list(0, null).get(0).getId(), null); + assertEquals(1, notebookRepoSync.list(0, anonymous).size()); + assertEquals(1, notebookRepoSync.list(1, anonymous).size()); + assertEquals(notebookRepoSync.list(0, anonymous).get(0).getId(),notebookRepoSync.list(1, anonymous).get(0).getId()); + + notebookSync.removeNote(notebookRepoSync.list(0, null).get(0).getId(), anonymous); } @Test public void testSyncOnDelete() throws IOException { /* create note */ assertTrue(notebookRepoSync.getRepoCount() > 1); - assertEquals(0, notebookRepoSync.list(0, null).size()); - assertEquals(0, notebookRepoSync.list(1, null).size()); + assertEquals(0, notebookRepoSync.list(0, anonymous).size()); + assertEquals(0, notebookRepoSync.list(1, anonymous).size()); - Note note = notebookSync.createNote(null); + Note note = notebookSync.createNote(anonymous); /* check that created in both storage systems */ - assertEquals(1, notebookRepoSync.list(0, null).size()); - assertEquals(1, notebookRepoSync.list(1, null).size()); - assertEquals(notebookRepoSync.list(0, null).get(0).getId(),notebookRepoSync.list(1, null).get(0).getId()); + assertEquals(1, notebookRepoSync.list(0, anonymous).size()); + assertEquals(1, notebookRepoSync.list(1, anonymous).size()); + assertEquals(notebookRepoSync.list(0, anonymous).get(0).getId(),notebookRepoSync.list(1, anonymous).get(0).getId()); /* remove Note */ - notebookSync.removeNote(notebookRepoSync.list(0, null).get(0).getId(), null); + notebookSync.removeNote(notebookRepoSync.list(0, anonymous).get(0).getId(), anonymous); /* check that deleted in both storages */ - assertEquals(0, notebookRepoSync.list(0, null).size()); - assertEquals(0, notebookRepoSync.list(1, null).size()); + assertEquals(0, notebookRepoSync.list(0, anonymous).size()); + assertEquals(0, notebookRepoSync.list(1, anonymous).size()); } @@ -160,7 +163,7 @@ public void testSyncOnDelete() throws IOException { public void testSyncUpdateMain() throws IOException { /* create note */ - Note note = notebookSync.createNote(null); + Note note = notebookSync.createNote(anonymous); Paragraph p1 = note.addParagraph(); Map config = p1.getConfig(); config.put("enabled", true); @@ -172,38 +175,38 @@ public void testSyncUpdateMain() throws IOException { /* new paragraph not yet saved into storages */ assertEquals(0, notebookRepoSync.get(0, - notebookRepoSync.list(0, null).get(0).getId(), null).getParagraphs().size()); + notebookRepoSync.list(0, anonymous).get(0).getId(), anonymous).getParagraphs().size()); assertEquals(0, notebookRepoSync.get(1, - notebookRepoSync.list(1, null).get(0).getId(), null).getParagraphs().size()); + notebookRepoSync.list(1, anonymous).get(0).getId(), anonymous).getParagraphs().size()); /* save to storage under index 0 (first storage) */ - notebookRepoSync.save(0, note, null); + notebookRepoSync.save(0, note, anonymous); /* check paragraph saved to first storage */ assertEquals(1, notebookRepoSync.get(0, - notebookRepoSync.list(0, null).get(0).getId(), null).getParagraphs().size()); + notebookRepoSync.list(0, anonymous).get(0).getId(), anonymous).getParagraphs().size()); /* check paragraph isn't saved to second storage */ assertEquals(0, notebookRepoSync.get(1, - notebookRepoSync.list(1, null).get(0).getId(), null).getParagraphs().size()); + notebookRepoSync.list(1, anonymous).get(0).getId(), anonymous).getParagraphs().size()); /* apply sync */ notebookRepoSync.sync(null); /* check whether added to second storage */ assertEquals(1, notebookRepoSync.get(1, - notebookRepoSync.list(1, null).get(0).getId(), null).getParagraphs().size()); + notebookRepoSync.list(1, anonymous).get(0).getId(), anonymous).getParagraphs().size()); /* check whether same paragraph id */ assertEquals(p1.getId(), notebookRepoSync.get(0, - notebookRepoSync.list(0, null).get(0).getId(), null).getLastParagraph().getId()); + notebookRepoSync.list(0, anonymous).get(0).getId(), anonymous).getLastParagraph().getId()); assertEquals(p1.getId(), notebookRepoSync.get(1, - notebookRepoSync.list(1, null).get(0).getId(), null).getLastParagraph().getId()); - notebookRepoSync.remove(note.getId(), null); + notebookRepoSync.list(1, anonymous).get(0).getId(), anonymous).getLastParagraph().getId()); + notebookRepoSync.remove(note.getId(), anonymous); } @Test public void testSyncOnReloadedList() throws IOException { /* check that both storage repos are empty */ assertTrue(notebookRepoSync.getRepoCount() > 1); - assertEquals(0, notebookRepoSync.list(0, null).size()); - assertEquals(0, notebookRepoSync.list(1, null).size()); + assertEquals(0, notebookRepoSync.list(0, anonymous).size()); + assertEquals(0, notebookRepoSync.list(1, anonymous).size()); File srcDir = new File("src/test/resources/2A94M5J1Z"); File destDir = new File(secNotebookDir + "/2A94M5J1Z"); @@ -214,13 +217,13 @@ public void testSyncOnReloadedList() throws IOException { } catch (IOException e) { LOG.error(e.toString(), e); } - assertEquals(0, notebookRepoSync.list(0, null).size()); - assertEquals(1, notebookRepoSync.list(1, null).size()); + assertEquals(0, notebookRepoSync.list(0, anonymous).size()); + assertEquals(1, notebookRepoSync.list(1, anonymous).size()); // After reloading notebooks repos should be synchronized - notebookSync.reloadAllNotes(null); - assertEquals(1, notebookRepoSync.list(0, null).size()); - assertEquals(1, notebookRepoSync.list(1, null).size()); + notebookSync.reloadAllNotes(anonymous); + assertEquals(1, notebookRepoSync.list(0, anonymous).size()); + assertEquals(1, notebookRepoSync.list(1, anonymous).size()); } @Test @@ -287,15 +290,15 @@ public void testCheckpointOneStorage() throws IOException, SchedulerException { GitNotebookRepo gitRepo = (GitNotebookRepo) vRepoSync.getRepo(0); // no notes - assertThat(vRepoSync.list(null).size()).isEqualTo(0); + assertThat(vRepoSync.list(anonymous).size()).isEqualTo(0); // create note - Note note = vNotebookSync.createNote(null); - assertThat(vRepoSync.list(null).size()).isEqualTo(1); + Note note = vNotebookSync.createNote(anonymous); + assertThat(vRepoSync.list(anonymous).size()).isEqualTo(1); - String noteId = vRepoSync.list(null).get(0).getId(); + String noteId = vRepoSync.list(anonymous).get(0).getId(); // first checkpoint - vRepoSync.checkpoint(noteId, "checkpoint message", null); - int vCount = gitRepo.revisionHistory(noteId, null).size(); + vRepoSync.checkpoint(noteId, "checkpoint message", anonymous); + int vCount = gitRepo.revisionHistory(noteId, anonymous).size(); assertThat(vCount).isEqualTo(1); Paragraph p = note.addParagraph(); @@ -305,10 +308,10 @@ public void testCheckpointOneStorage() throws IOException, SchedulerException { p.setText("%md checkpoint test"); // save and checkpoint again - vRepoSync.save(note, null); - vRepoSync.checkpoint(noteId, "checkpoint message 2", null); - assertThat(gitRepo.revisionHistory(noteId, null).size()).isEqualTo(vCount + 1); - notebookRepoSync.remove(note.getId(), null); + vRepoSync.save(note, anonymous); + vRepoSync.checkpoint(noteId, "checkpoint message 2", anonymous); + assertThat(gitRepo.revisionHistory(noteId, anonymous).size()).isEqualTo(vCount + 1); + notebookRepoSync.remove(note.getId(), anonymous); } static void delete(File file){ diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java index 9fc2d826251..e6236c85a21 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java @@ -32,10 +32,12 @@ import org.apache.zeppelin.interpreter.InterpreterOption; import org.apache.zeppelin.interpreter.mock.MockInterpreter1; import org.apache.zeppelin.notebook.*; +import org.apache.zeppelin.notebook.repo.zeppelinhub.security.Authentication; import org.apache.zeppelin.scheduler.JobListener; import org.apache.zeppelin.scheduler.SchedulerFactory; import org.apache.zeppelin.search.SearchService; import org.apache.zeppelin.search.LuceneSearch; +import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -76,7 +78,7 @@ public void setUp() throws Exception { this.schedulerFactory = new SchedulerFactory(); depResolver = new DependencyResolver(mainZepDir.getAbsolutePath() + "/local-repo"); - factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver); + factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false); SearchService search = mock(SearchService.class); notebookRepo = new VFSNotebookRepo(conf); @@ -106,14 +108,16 @@ public void testInvalidJsonFile() throws IOException { @Test public void testSaveNotebook() throws IOException, InterruptedException { - Note note = notebook.createNote(null); - factory.setInterpreters(note.getId(), factory.getDefaultInterpreterSettingList()); + AuthenticationInfo anonymous = new AuthenticationInfo("anonymous"); + Note note = notebook.createNote(anonymous); + factory.setInterpreters("user", note.getId(), factory.getDefaultInterpreterSettingList()); Paragraph p1 = note.addParagraph(); Map config = p1.getConfig(); config.put("enabled", true); p1.setConfig(config); p1.setText("%mock1 hello world"); + p1.setAuthenticationInfo(anonymous); note.run(p1.getId()); int timeout = 1; diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/search/LuceneSearchTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/search/LuceneSearchTest.java index 81c4b81329b..bf4d9aa494c 100644 --- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/search/LuceneSearchTest.java +++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/search/LuceneSearchTest.java @@ -29,6 +29,7 @@ import org.apache.zeppelin.notebook.Note; import org.apache.zeppelin.notebook.Paragraph; import org.apache.zeppelin.notebook.repo.NotebookRepo; +import org.apache.zeppelin.user.AuthenticationInfo; import org.junit.After; import org.junit.Before; import org.junit.BeforeClass; @@ -41,6 +42,7 @@ public class LuceneSearchTest { private static NotebookRepo notebookRepoMock; private static InterpreterFactory interpreterFactory; private SearchService notebookIndex; + private AuthenticationInfo anonymous; @BeforeClass public static void beforeStartUp() { @@ -54,6 +56,7 @@ public static void beforeStartUp() { @Before public void startUp() { notebookIndex = new LuceneSearch(); + anonymous = new AuthenticationInfo("anonymous"); } @After @@ -202,7 +205,7 @@ public void canNotSearchBeforeIndexing() { //when Paragraph p1 = note1.getLastParagraph(); p1.setText("no no no"); - note1.persist(null); + note1.persist(anonymous); //then assertThat(resultForQuery("Notebook1").size()).isEqualTo(1); @@ -226,7 +229,7 @@ public void canNotSearchBeforeIndexing() { //when note1.setName("NotebookN"); - note1.persist(null); + note1.persist(anonymous); //then assertThat(resultForQuery("Notebook1")).isEmpty();