You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by jo...@apache.org on 2017/03/03 07:48:00 UTC

zeppelin git commit: [HOTFIX][ZEPPELIN-2178] Prevent from cleaning output in Personalized mode

Repository: zeppelin
Updated Branches:
  refs/heads/master bab985461 -> d294a765a


[HOTFIX][ZEPPELIN-2178] Prevent from cleaning output in Personalized mode

### What is this PR for?
Fixing empty output issue while using personalized mode.

### What type of PR is it?
[Hot Fix]

### Todos
* [x] - Making default user's paragraph while accessing at the first time.

### What is the Jira issue?
* https://issues.apache.org/jira/browse/ZEPPELIN-2178

### How should this be tested?
Use personalized mode

### Screenshots (if appropriate)
N/A

### Questions:
* Does the licenses files need update? No
* Is there breaking changes for older versions? No
* Does this needs documentation? No

Author: Jongyoul Lee <jo...@gmail.com>

Closes #2084 from jongyoul/ZEPPELIN-2178 and squashes the following commits:

5e3ac05 [Jongyoul Lee] Fixed the style
1ffbe00 [Jongyoul Lee] Prevent from broadcasting to all users
2d0d7ca [Jongyoul Lee] Fixed that output and text became reverted into previous status Updated status after running paragraph
47c978f [Jongyoul Lee] Clean outputs when users turn off personalized mode
a190f2f [Jongyoul Lee] Fix the initial status to READY
faacb5f [Jongyoul Lee] Prevent from cleaning output in Personalized mode


Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo
Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/d294a765
Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/d294a765
Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/d294a765

Branch: refs/heads/master
Commit: d294a765a2ebefdcf046e8706719517be4ea698a
Parents: bab9854
Author: Jongyoul Lee <jo...@gmail.com>
Authored: Thu Mar 2 02:04:06 2017 +0900
Committer: Jongyoul Lee <jo...@apache.org>
Committed: Fri Mar 3 16:47:47 2017 +0900

----------------------------------------------------------------------
 .../apache/zeppelin/socket/NotebookServer.java  |  39 +++++--
 .../java/org/apache/zeppelin/notebook/Note.java |   9 ++
 .../org/apache/zeppelin/notebook/Paragraph.java |  34 ++++--
 .../apache/zeppelin/notebook/ParagraphTest.java | 107 +++++++++++++++++++
 4 files changed, 173 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d294a765/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
----------------------------------------------------------------------
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 ee88375..8670ed1 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
@@ -1184,15 +1184,21 @@ public class NotebookServer extends WebSocketServlet
     final Note note = notebook.getNote(noteId);
     Paragraph p = note.getParagraph(paragraphId);
 
-    AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal);
-    if (note.isPersonalizedMode()) {
-      p = p.getUserParagraphMap().get(subject.getUser());
-    }
-
     p.settings.setParams(params);
     p.setConfig(config);
     p.setTitle((String) fromMessage.get("title"));
     p.setText((String) fromMessage.get("paragraph"));
+
+    AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal);
+    if (note.isPersonalizedMode()) {
+      p = p.getUserParagraph(subject.getUser());
+      p.settings.setParams(params);
+      p.setConfig(config);
+      p.setTitle((String) fromMessage.get("title"));
+      p.setText((String) fromMessage.get("paragraph"));
+    }
+
+
     note.persist(subject);
 
     if (note.isPersonalizedMode()) {
@@ -1759,6 +1765,15 @@ public class NotebookServer extends WebSocketServlet
     p.settings.setParams(params);
     p.setConfig(config);
 
+    if (note.isPersonalizedMode()) {
+      p = note.getParagraph(paragraphId);
+      p.setText(text);
+      p.setTitle(title);
+      p.setAuthenticationInfo(subject);
+      p.settings.setParams(params);
+      p.setConfig(config);
+    }
+
     return p;
   }
 
@@ -1877,7 +1892,15 @@ public class NotebookServer extends WebSocketServlet
       InterpreterResult.Type type, String output) {
     Message msg = new Message(OP.PARAGRAPH_UPDATE_OUTPUT).put("noteId", noteId)
         .put("paragraphId", paragraphId).put("index", index).put("type", type).put("data", output);
-    broadcast(noteId, msg);
+    Note note = notebook().getNote(noteId);
+    if (note.isPersonalizedMode()) {
+      String user = note.getParagraph(paragraphId).getUser();
+      if (null != user) {
+        multicastToUser(user, msg);
+      }
+    } else {
+      broadcast(noteId, msg);
+    }
   }
 
 
@@ -2146,7 +2169,9 @@ public class NotebookServer extends WebSocketServlet
         }
       }
       if (job instanceof Paragraph) {
-        notebookServer.broadcastParagraph(note, (Paragraph) job);
+        Paragraph p = (Paragraph) job;
+        p.setStatusToUserParagraph(job.getStatus());
+        notebookServer.broadcastParagraph(note, p);
       }
       try {
         notebookServer.broadcastUpdateNoteJobInfo(System.currentTimeMillis() - 5000);

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d294a765/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java
----------------------------------------------------------------------
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 827f862..0463c6b 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
@@ -137,6 +137,15 @@ public class Note implements Serializable, ParagraphJobListener {
       valueString = "false";
     }
     getConfig().put("personalizedMode", valueString);
+    clearUserParagraphs(value);
+  }
+
+  private void clearUserParagraphs(boolean isPersonalized) {
+    if (!isPersonalized) {
+      for (Paragraph p : paragraphs) {
+        p.clearUserParagraphs();
+      }
+    }
   }
 
   public String getId() {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d294a765/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
----------------------------------------------------------------------
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 1bf693c..f5cf15d 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
@@ -49,6 +49,7 @@ import com.google.common.annotations.VisibleForTesting;
  * Paragraph is a representation of an execution unit.
  */
 public class Paragraph extends Job implements Serializable, Cloneable {
+
   private static final long serialVersionUID = -6328572073497992016L;
 
   private static Logger logger = LoggerFactory.getLogger(Paragraph.class);
@@ -124,6 +125,9 @@ public class Paragraph extends Job implements Serializable, Cloneable {
   }
 
   public Paragraph getUserParagraph(String user) {
+    if (!userParagraphMap.containsKey(user)) {
+      cloneParagraphForUser(user);
+    }
     return userParagraphMap.get(user);
   }
 
@@ -140,12 +144,16 @@ public class Paragraph extends Job implements Serializable, Cloneable {
     p.setTitle(getTitle());
     p.setText(getText());
     p.setResult(getReturn());
-    p.setStatus(getStatus());
+    p.setStatus(Status.READY);
     p.setId(getId());
     addUser(p, user);
     return p;
   }
 
+  public void clearUserParagraphs() {
+    userParagraphMap.clear();
+  }
+
   public void addUser(Paragraph p, String user) {
     userParagraphMap.put(user, p);
   }
@@ -371,6 +379,10 @@ public class Paragraph extends Job implements Serializable, Cloneable {
       }
     }
 
+    for (Paragraph p : userParagraphMap.values()) {
+      p.setText(getText());
+    }
+
     String script = getScriptBody();
     // inject form
     if (repl.getFormType() == FormType.NATIVE) {
@@ -402,13 +414,9 @@ public class Paragraph extends Job implements Serializable, Cloneable {
       List<InterpreterResultMessage> resultMessages = context.out.toInterpreterResultMessage();
       resultMessages.addAll(ret.message());
 
-      for (Paragraph p : userParagraphMap.values()) {
-        p.setText(getText());
-      }
-
       InterpreterResult res = new InterpreterResult(ret.code(), resultMessages);
 
-      Paragraph p = userParagraphMap.get(getUser());
+      Paragraph p = getUserParagraph(getUser());
       if (null != p) {
         p.setResult(res);
         p.settings.setParams(settings.getParams());
@@ -527,12 +535,12 @@ public class Paragraph extends Job implements Serializable, Cloneable {
     Credentials credentials = note.getCredentials();
     if (authenticationInfo != null) {
       UserCredentials userCredentials =
-              credentials.getUserCredentials(authenticationInfo.getUser());
+          credentials.getUserCredentials(authenticationInfo.getUser());
       authenticationInfo.setUserCredentials(userCredentials);
     }
 
     InterpreterContext interpreterContext =
-            new InterpreterContext(note.getId(), getId(), getRequiredReplName(), this.getTitle(),
+        new InterpreterContext(note.getId(), getId(), getRequiredReplName(), this.getTitle(),
             this.getText(), this.getAuthenticationInfo(), this.getConfig(), this.settings, registry,
             resourcePool, runners, output);
     return interpreterContext;
@@ -575,7 +583,15 @@ public class Paragraph extends Job implements Serializable, Cloneable {
     return new ParagraphRunner(note, note.getId(), getId());
   }
 
+  public void setStatusToUserParagraph(Status status) {
+    String user = getUser();
+    if (null != user) {
+      getUserParagraph(getUser()).setStatus(status);
+    }
+  }
+
   static class ParagraphRunner extends InterpreterContextRunner {
+
     private transient Note note;
 
     public ParagraphRunner(Note note, String noteId, String paragraphId) {
@@ -700,7 +716,7 @@ public class Paragraph extends Job implements Serializable, Cloneable {
       for (String key : infos.keySet()) {
         ParagraphRuntimeInfo info = this.runtimeInfos.get(key);
         if (info == null) {
-          info = new ParagraphRuntimeInfo(key, label, tooltip,  group, intpSettingId);
+          info = new ParagraphRuntimeInfo(key, label, tooltip, group, intpSettingId);
           this.runtimeInfos.put(key, info);
         }
         info.addValue(infos.get(key));

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/d294a765/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
index 69577e9..0e77846 100644
--- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
+++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/ParagraphTest.java
@@ -19,22 +19,48 @@ package org.apache.zeppelin.notebook;
 
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyObject;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import com.google.common.collect.Lists;
+import java.util.List;
 import org.apache.zeppelin.display.AngularObject;
 import org.apache.zeppelin.display.AngularObjectBuilder;
 import org.apache.zeppelin.display.AngularObjectRegistry;
 import org.apache.zeppelin.display.Input;
 import org.apache.zeppelin.interpreter.Interpreter;
+import org.apache.zeppelin.interpreter.Interpreter.FormType;
+import org.apache.zeppelin.interpreter.InterpreterContext;
 import org.apache.zeppelin.interpreter.InterpreterFactory;
+import org.apache.zeppelin.interpreter.InterpreterGroup;
+import org.apache.zeppelin.interpreter.InterpreterOption;
+import org.apache.zeppelin.interpreter.InterpreterResult;
+import org.apache.zeppelin.interpreter.InterpreterResult.Code;
+import org.apache.zeppelin.interpreter.InterpreterResult.Type;
+import org.apache.zeppelin.interpreter.InterpreterResultMessage;
+import org.apache.zeppelin.interpreter.InterpreterSetting;
+import org.apache.zeppelin.interpreter.InterpreterSetting.Status;
+import org.apache.zeppelin.interpreter.InterpreterSettingManager;
+import org.apache.zeppelin.resource.ResourcePool;
+import org.apache.zeppelin.scheduler.JobListener;
+import org.apache.zeppelin.user.AuthenticationInfo;
+import org.apache.zeppelin.user.Credentials;
 import org.junit.Test;
 
 import java.util.HashMap;
 import java.util.Map;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
 
 public class ParagraphTest {
   @Test
@@ -125,4 +151,85 @@ public class ParagraphTest {
     verify(registry).get("age", noteId, null);
     assertEquals(actual, expected);
   }
+
+  @Test
+  public void returnDefaultParagraphWithNewUser() {
+    Paragraph p = new Paragraph("para_1", null, null, null, null);
+    Object defaultValue = "Default Value";
+    p.setResult(defaultValue);
+    Paragraph newUserParagraph = p.getUserParagraph("new_user");
+    assertNotNull(newUserParagraph);
+    assertEquals(defaultValue, newUserParagraph.getReturn());
+  }
+
+  @Test
+  public void returnUnchangedResultsWithDifferentUser() throws Throwable {
+    InterpreterSettingManager mockInterpreterSettingManager = mock(InterpreterSettingManager.class);
+    Note mockNote = mock(Note.class);
+    when(mockNote.getCredentials()).thenReturn(mock(Credentials.class));
+    Paragraph spyParagraph = spy(new Paragraph("para_1", mockNote,  null, null, mockInterpreterSettingManager));
+
+    doReturn("spy").when(spyParagraph).getRequiredReplName();
+
+
+    Interpreter mockInterpreter = mock(Interpreter.class);
+    doReturn(mockInterpreter).when(spyParagraph).getRepl(anyString());
+
+    InterpreterGroup mockInterpreterGroup = mock(InterpreterGroup.class);
+    when(mockInterpreter.getInterpreterGroup()).thenReturn(mockInterpreterGroup);
+    when(mockInterpreterGroup.getId()).thenReturn("mock_id_1");
+    when(mockInterpreterGroup.getAngularObjectRegistry()).thenReturn(mock(AngularObjectRegistry.class));
+    when(mockInterpreterGroup.getResourcePool()).thenReturn(mock(ResourcePool.class));
+
+    List<InterpreterSetting> spyInterpreterSettingList = spy(Lists.<InterpreterSetting>newArrayList());
+    InterpreterSetting mockInterpreterSetting = mock(InterpreterSetting.class);
+    InterpreterOption mockInterpreterOption = mock(InterpreterOption.class);
+    when(mockInterpreterSetting.getOption()).thenReturn(mockInterpreterOption);
+    when(mockInterpreterOption.permissionIsSet()).thenReturn(false);
+    when(mockInterpreterSetting.getStatus()).thenReturn(Status.READY);
+    when(mockInterpreterSetting.getId()).thenReturn("mock_id_1");
+    when(mockInterpreterSetting.getInterpreterGroup(anyString(), anyString())).thenReturn(mockInterpreterGroup);
+    spyInterpreterSettingList.add(mockInterpreterSetting);
+    when(mockNote.getId()).thenReturn("any_id");
+    when(mockInterpreterSettingManager.getInterpreterSettings(anyString())).thenReturn(spyInterpreterSettingList);
+
+    doReturn("spy script body").when(spyParagraph).getScriptBody();
+
+    when(mockInterpreter.getFormType()).thenReturn(FormType.NONE);
+
+    ParagraphJobListener mockJobListener = mock(ParagraphJobListener.class);
+    doReturn(mockJobListener).when(spyParagraph).getListener();
+    doNothing().when(mockJobListener).onOutputUpdateAll(Mockito.<Paragraph>any(), Mockito.anyList());
+
+    InterpreterResult mockInterpreterResult = mock(InterpreterResult.class);
+    when(mockInterpreter.interpret(anyString(), Mockito.<InterpreterContext>any())).thenReturn(mockInterpreterResult);
+    when(mockInterpreterResult.code()).thenReturn(Code.SUCCESS);
+
+
+    // Actual test
+    List<InterpreterResultMessage> result1 = Lists.newArrayList();
+    result1.add(new InterpreterResultMessage(Type.TEXT, "result1"));
+    when(mockInterpreterResult.message()).thenReturn(result1);
+
+    AuthenticationInfo user1 = new AuthenticationInfo("user1");
+    spyParagraph.setAuthenticationInfo(user1);
+    spyParagraph.jobRun();
+    Paragraph p1 = spyParagraph.getUserParagraph(user1.getUser());
+
+    List<InterpreterResultMessage> result2 = Lists.newArrayList();
+    result2.add(new InterpreterResultMessage(Type.TEXT, "result2"));
+    when(mockInterpreterResult.message()).thenReturn(result2);
+
+    AuthenticationInfo user2 = new AuthenticationInfo("user2");
+    spyParagraph.setAuthenticationInfo(user2);
+    spyParagraph.jobRun();
+    Paragraph p2 = spyParagraph.getUserParagraph(user2.getUser());
+
+    assertNotEquals(p1.getReturn().toString(), p2.getReturn().toString());
+
+    assertEquals(p1, spyParagraph.getUserParagraph(user1.getUser()));
+
+
+
+  }
 }