mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Merge branch 'master' into extends-zrun-remote-transaction
# Conflicts: # zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreter.java # zeppelin-interpreter/src/main/thrift/RemoteInterpreterService.thrift # zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteAngularObjectTest.java # zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterOutputTestStream.java # zeppelin-interpreter/src/test/java/org/apache/zeppelin/interpreter/remote/RemoteInterpreterTest.java # zeppelin-interpreter/src/test/java/org/apache/zeppelin/resource/DistributedResourcePoolTest.java # zeppelin-interpreter/src/test/java/org/apache/zeppelin/scheduler/RemoteSchedulerTest.java # zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
This commit is contained in:
commit
8d42c166a3
24 changed files with 217 additions and 66 deletions
|
|
@ -23,7 +23,7 @@ function usage() {
|
|||
echo "usage) $0 -p <port> -d <interpreter dir to load> -l <local interpreter repo dir to load>"
|
||||
}
|
||||
|
||||
while getopts "hp:d:l:v" o; do
|
||||
while getopts "hp:d:l:v:u:" o; do
|
||||
case ${o} in
|
||||
h)
|
||||
usage
|
||||
|
|
@ -42,6 +42,14 @@ while getopts "hp:d:l:v" o; do
|
|||
. "${bin}/common.sh"
|
||||
getZeppelinVersion
|
||||
;;
|
||||
u)
|
||||
ZEPPELIN_IMPERSONATE_USER="${OPTARG}"
|
||||
if [[ -z "$ZEPPELIN_IMPERSONATE_CMD" ]]; then
|
||||
ZEPPELIN_IMPERSONATE_RUN_CMD=`echo "ssh ${ZEPPELIN_IMPERSONATE_USER}@localhost" `
|
||||
else
|
||||
ZEPPELIN_IMPERSONATE_RUN_CMD=$(eval "echo ${ZEPPELIN_IMPERSONATE_CMD} ")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
|
|
@ -178,9 +186,9 @@ addJarInDirForIntp "${LOCAL_INTERPRETER_REPO}"
|
|||
CLASSPATH+=":${ZEPPELIN_INTP_CLASSPATH}"
|
||||
|
||||
if [[ -n "${SPARK_SUBMIT}" ]]; then
|
||||
${SPARK_SUBMIT} --class ${ZEPPELIN_SERVER} --driver-class-path "${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH}" --driver-java-options "${JAVA_INTP_OPTS}" ${SPARK_SUBMIT_OPTIONS} ${SPARK_APP_JAR} ${PORT} &
|
||||
${ZEPPELIN_IMPERSONATE_RUN_CMD} `${SPARK_SUBMIT} --class ${ZEPPELIN_SERVER} --driver-class-path "${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH}" --driver-java-options "${JAVA_INTP_OPTS}" ${SPARK_SUBMIT_OPTIONS} ${SPARK_APP_JAR} ${PORT} &`
|
||||
else
|
||||
${ZEPPELIN_RUNNER} ${JAVA_INTP_OPTS} ${ZEPPELIN_INTP_MEM} -cp ${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH} ${ZEPPELIN_SERVER} ${PORT} &
|
||||
${ZEPPELIN_IMPERSONATE_RUN_CMD} ${ZEPPELIN_RUNNER} ${JAVA_INTP_OPTS} ${ZEPPELIN_INTP_MEM} -cp ${ZEPPELIN_INTP_CLASSPATH_OVERRIDES}:${CLASSPATH} ${ZEPPELIN_SERVER} ${PORT} &
|
||||
fi
|
||||
|
||||
pid=$!
|
||||
|
|
|
|||
|
|
@ -79,3 +79,4 @@
|
|||
# export ZEPPELINHUB_API_ADDRESS # Refers to the address of the ZeppelinHub service in use
|
||||
# export ZEPPELINHUB_API_TOKEN # Refers to the Zeppelin instance token of the user
|
||||
# export ZEPPELINHUB_USER_KEY # Optional, when using Zeppelin with authentication.
|
||||
# export ZEPPELIN_IMPERSONATE_CMD # Optional, when user want to run interpreter as end web user. eg) 'sudo -u ${ZEPPELIN_IMPERSONATE_USER}'
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
<li><a href="{{BASE_PATH}}/manual/interpreterinstallation.html">Interpreter Installation</a></li>
|
||||
<!--<li><a href="{{BASE_PATH}}/manual/dynamicinterpreterload.html">Dynamic Interpreter Loading</a></li>-->
|
||||
<li><a href="{{BASE_PATH}}/manual/dependencymanagement.html">Interpreter Dependency Management</a></li>
|
||||
<li><a href="{{BASE_PATH}}/manual/userimpersonation.html">Interpreter User Impersonation</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="title"><span><b>Available Interpreters</b><span></li>
|
||||
<li><a href="{{BASE_PATH}}/interpreter/alluxio.html">Alluxio</a></li>
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 892 KiB |
|
|
@ -142,6 +142,7 @@ Join to our [Mailing list](https://zeppelin.apache.org/community.html) and repor
|
|||
* Usage
|
||||
* [Interpreter Installation](./manual/interpreterinstallation.html): Install not only community managed interpreters but also 3rd party interpreters
|
||||
* [Interpreter Dependency Management](./manual/dependencymanagement.html) when you include external libraries to interpreter
|
||||
* [Interpreter User Impersonation](./manual/userimpersonation.html) when you want to run interpreter as end user
|
||||
* Available Interpreters: currently, about 20 interpreters are available in Apache Zeppelin.
|
||||
|
||||
####Display System
|
||||
|
|
|
|||
66
docs/manual/processenduser.md
Normal file
66
docs/manual/processenduser.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
---
|
||||
layout: page
|
||||
title: "Run zeppelin interpreter process as web front end user"
|
||||
description: "Set up zeppelin interpreter process as web front end user."
|
||||
group: manual
|
||||
---
|
||||
<!--
|
||||
Licensed 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.
|
||||
-->
|
||||
{% include JB/setup %}
|
||||
|
||||
## Run zeppelin interpreter process as web front end user
|
||||
|
||||
* Enable shiro auth in shiro.ini
|
||||
|
||||
```
|
||||
[users]
|
||||
user1 = password1, role1
|
||||
user2 = password2, role2
|
||||
```
|
||||
|
||||
* Enable password-less ssh for the user you want to impersonate (say user1).
|
||||
|
||||
```
|
||||
adduser user1
|
||||
#ssh-keygen (optional if you don't already have generated ssh-key.
|
||||
ssh user1@localhost mkdir -p .ssh
|
||||
cat ~/.ssh/id_rsa.pub | ssh user1@localhost 'cat >> .ssh/authorized_keys'
|
||||
```
|
||||
|
||||
* Start zeppelin server.
|
||||
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<b> Screenshot </b>
|
||||
<br /><br />
|
||||
</div>
|
||||
<div class="col-md-12" >
|
||||
<a data-lightbox="compiler" href="../assets/themes/zeppelin/img/screenshots/user-impersonation.gif">
|
||||
<img class="img-responsive" src="../assets/themes/zeppelin/img/screenshots/user-impersonation.gif" />
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
* Go to interpreter setting page, and enable "User Impersonate" in any of the interpreter (in my example its shell interpreter)
|
||||
|
||||
* Test with a simple paragraph
|
||||
|
||||
```
|
||||
%sh
|
||||
whoami
|
||||
```
|
||||
|
||||
|
|
@ -37,6 +37,7 @@ public class InterpreterOption {
|
|||
boolean isExistingProcess;
|
||||
boolean setPermission;
|
||||
List<String> users;
|
||||
boolean isUserImpersonate;
|
||||
|
||||
public boolean isExistingProcess() {
|
||||
return isExistingProcess;
|
||||
|
|
@ -66,6 +67,14 @@ public class InterpreterOption {
|
|||
return users;
|
||||
}
|
||||
|
||||
public boolean isUserImpersonate() {
|
||||
return isUserImpersonate;
|
||||
}
|
||||
|
||||
public void setUserImpersonate(boolean userImpersonate) {
|
||||
isUserImpersonate = userImpersonate;
|
||||
}
|
||||
|
||||
public InterpreterOption() {
|
||||
this(false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
private int maxPoolSize;
|
||||
private String host;
|
||||
private int port;
|
||||
private String userName;
|
||||
private Boolean isUserImpersonate;
|
||||
|
||||
/**
|
||||
* Remote interpreter and manage interpreter process
|
||||
|
|
@ -74,7 +76,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
int maxPoolSize,
|
||||
RemoteInterpreterProcessListener remoteInterpreterProcessListener,
|
||||
ApplicationEventListener appListener,
|
||||
RemoteWorksController remoteWorksController) {
|
||||
String userName,
|
||||
Boolean isUserImpersonate) {
|
||||
super(property);
|
||||
this.noteId = noteId;
|
||||
this.className = className;
|
||||
|
|
@ -87,7 +90,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
this.maxPoolSize = maxPoolSize;
|
||||
this.remoteInterpreterProcessListener = remoteInterpreterProcessListener;
|
||||
this.applicationEventListener = appListener;
|
||||
this.remoteWorksController = remoteWorksController;
|
||||
this.userName = userName;
|
||||
this.isUserImpersonate = isUserImpersonate;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -104,7 +108,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
int maxPoolSize,
|
||||
RemoteInterpreterProcessListener remoteInterpreterProcessListener,
|
||||
ApplicationEventListener appListener,
|
||||
RemoteWorksController remoteWorksController) {
|
||||
String userName,
|
||||
Boolean isUserImpersonate) {
|
||||
super(property);
|
||||
this.noteId = noteId;
|
||||
this.className = className;
|
||||
|
|
@ -115,7 +120,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
this.maxPoolSize = maxPoolSize;
|
||||
this.remoteInterpreterProcessListener = remoteInterpreterProcessListener;
|
||||
this.applicationEventListener = appListener;
|
||||
this.remoteWorksController = remoteWorksController;
|
||||
this.userName = userName;
|
||||
this.isUserImpersonate = isUserImpersonate;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -131,7 +137,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
int connectTimeout,
|
||||
RemoteInterpreterProcessListener remoteInterpreterProcessListener,
|
||||
ApplicationEventListener appListener,
|
||||
RemoteWorksController remoteWorksController) {
|
||||
String userName,
|
||||
Boolean isUserImpersonate) {
|
||||
super(property);
|
||||
this.className = className;
|
||||
this.noteId = noteId;
|
||||
|
|
@ -144,7 +151,8 @@ public class RemoteInterpreter extends Interpreter {
|
|||
this.maxPoolSize = 10;
|
||||
this.remoteInterpreterProcessListener = remoteInterpreterProcessListener;
|
||||
this.applicationEventListener = appListener;
|
||||
this.remoteWorksController = remoteWorksController;
|
||||
this.userName = userName;
|
||||
this.isUserImpersonate = isUserImpersonate;
|
||||
}
|
||||
|
||||
private Map<String, String> getEnvFromInterpreterProperty(Properties property) {
|
||||
|
|
@ -214,7 +222,7 @@ public class RemoteInterpreter extends Interpreter {
|
|||
RemoteInterpreterProcess interpreterProcess = getInterpreterProcess();
|
||||
|
||||
final InterpreterGroup interpreterGroup = getInterpreterGroup();
|
||||
interpreterProcess.reference(interpreterGroup);
|
||||
interpreterProcess.reference(interpreterGroup, userName, isUserImpersonate);
|
||||
interpreterProcess.setMaxPoolSize(
|
||||
Math.max(this.maxPoolSize, interpreterProcess.getMaxPoolSize()));
|
||||
String groupId = interpreterGroup.getId();
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ public class RemoteInterpreterManagedProcess extends RemoteInterpreterProcess
|
|||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
public void start(String userName, Boolean isUserImpersonate) {
|
||||
// start server process
|
||||
try {
|
||||
port = RemoteInterpreterUtils.findRandomAvailablePortOnAllLocalInterfaces();
|
||||
|
|
@ -106,6 +106,10 @@ public class RemoteInterpreterManagedProcess extends RemoteInterpreterProcess
|
|||
cmdLine.addArgument(interpreterDir, false);
|
||||
cmdLine.addArgument("-p", false);
|
||||
cmdLine.addArgument(Integer.toString(port), false);
|
||||
if (isUserImpersonate && !userName.equals("anonymous")) {
|
||||
cmdLine.addArgument("-u", false);
|
||||
cmdLine.addArgument(userName, false);
|
||||
}
|
||||
cmdLine.addArgument("-l", false);
|
||||
cmdLine.addArgument(localRepoDir, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ public abstract class RemoteInterpreterProcess {
|
|||
|
||||
public abstract String getHost();
|
||||
public abstract int getPort();
|
||||
public abstract void start();
|
||||
public abstract void start(String userName, Boolean isUserImpersonate);
|
||||
public abstract void stop();
|
||||
public abstract boolean isRunning();
|
||||
|
||||
|
|
@ -73,10 +73,11 @@ public abstract class RemoteInterpreterProcess {
|
|||
return connectTimeout;
|
||||
}
|
||||
|
||||
public int reference(InterpreterGroup interpreterGroup) {
|
||||
public int reference(InterpreterGroup interpreterGroup, String userName,
|
||||
Boolean isUserImpersonate) {
|
||||
synchronized (referenceCount) {
|
||||
if (!isRunning()) {
|
||||
start();
|
||||
start(userName, isUserImpersonate);
|
||||
}
|
||||
|
||||
if (clientPool == null) {
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class RemoteInterpreterRunningProcess extends RemoteInterpreterProcess {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
public void start(String userName, Boolean isUserImpersonate) {
|
||||
// assume process is externally managed. nothing to do
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ public class RemoteAngularObjectTest implements AngularObjectRegistryListener {
|
|||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
"anonymous",
|
||||
false
|
||||
);
|
||||
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ public class RemoteInterpreterOutputTestStream implements RemoteInterpreterProce
|
|||
10 * 1000,
|
||||
this,
|
||||
null,
|
||||
null);
|
||||
"anonymous",
|
||||
false);
|
||||
|
||||
intpGroup.get("note").add(intp);
|
||||
intp.setInterpreterGroup(intpGroup);
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ public class RemoteInterpreterProcessTest {
|
|||
10 * 1000, null, null, null);
|
||||
assertFalse(rip.isRunning());
|
||||
assertEquals(0, rip.referenceCount());
|
||||
assertEquals(1, rip.reference(intpGroup));
|
||||
assertEquals(2, rip.reference(intpGroup));
|
||||
assertEquals(1, rip.reference(intpGroup, "anonymous", false));
|
||||
assertEquals(2, rip.reference(intpGroup, "anonymous", false));
|
||||
assertEquals(true, rip.isRunning());
|
||||
assertEquals(1, rip.dereference());
|
||||
assertEquals(true, rip.isRunning());
|
||||
|
|
@ -61,7 +61,7 @@ public class RemoteInterpreterProcessTest {
|
|||
RemoteInterpreterManagedProcess rip = new RemoteInterpreterManagedProcess(
|
||||
INTERPRETER_SCRIPT, "nonexists", "fakeRepo", new HashMap<String, String>(),
|
||||
mock(RemoteInterpreterEventPoller.class), 10 * 1000);
|
||||
rip.reference(intpGroup);
|
||||
rip.reference(intpGroup, "anonymous", false);
|
||||
assertEquals(0, rip.getNumActiveClient());
|
||||
assertEquals(0, rip.getNumIdleClient());
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ public class RemoteInterpreterProcessTest {
|
|||
, 10 * 1000);
|
||||
assertFalse(rip.isRunning());
|
||||
assertEquals(0, rip.referenceCount());
|
||||
assertEquals(1, rip.reference(intpGroup));
|
||||
assertEquals(1, rip.reference(intpGroup, "anonymous", false));
|
||||
assertEquals(true, rip.isRunning());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,17 +81,18 @@ public class RemoteInterpreterTest {
|
|||
|
||||
private RemoteInterpreter createMockInterpreterA(Properties p, String noteId) {
|
||||
return new RemoteInterpreter(
|
||||
p,
|
||||
noteId,
|
||||
MockInterpreterA.class.getName(),
|
||||
new File(INTERPRETER_SCRIPT).getAbsolutePath(),
|
||||
"fake",
|
||||
"fakeRepo",
|
||||
env,
|
||||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
p,
|
||||
noteId,
|
||||
MockInterpreterA.class.getName(),
|
||||
new File(INTERPRETER_SCRIPT).getAbsolutePath(),
|
||||
"fake",
|
||||
"fakeRepo",
|
||||
env,
|
||||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
"anonymous",
|
||||
false);
|
||||
}
|
||||
|
||||
private RemoteInterpreter createMockInterpreterB(Properties p) {
|
||||
|
|
@ -100,17 +101,18 @@ public class RemoteInterpreterTest {
|
|||
|
||||
private RemoteInterpreter createMockInterpreterB(Properties p, String noteId) {
|
||||
return new RemoteInterpreter(
|
||||
p,
|
||||
noteId,
|
||||
MockInterpreterB.class.getName(),
|
||||
new File(INTERPRETER_SCRIPT).getAbsolutePath(),
|
||||
"fake",
|
||||
"fakeRepo",
|
||||
env,
|
||||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
p,
|
||||
noteId,
|
||||
MockInterpreterB.class.getName(),
|
||||
new File(INTERPRETER_SCRIPT).getAbsolutePath(),
|
||||
"fake",
|
||||
"fakeRepo",
|
||||
env,
|
||||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
"anonymous",
|
||||
false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -210,8 +212,8 @@ public class RemoteInterpreterTest {
|
|||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
"anonymous",
|
||||
false);
|
||||
|
||||
intpGroup.get("note").add(intpA);
|
||||
intpA.setInterpreterGroup(intpGroup);
|
||||
|
|
@ -227,7 +229,8 @@ public class RemoteInterpreterTest {
|
|||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
"anonymous",
|
||||
false);
|
||||
|
||||
intpGroup.get("note").add(intpB);
|
||||
intpB.setInterpreterGroup(intpGroup);
|
||||
|
|
@ -691,8 +694,8 @@ public class RemoteInterpreterTest {
|
|||
//Given
|
||||
final Client client = Mockito.mock(Client.class);
|
||||
final RemoteInterpreter intr = new RemoteInterpreter(new Properties(), "noteId",
|
||||
MockInterpreterA.class.getName(),
|
||||
"runner", "path","localRepo", env, 10 * 1000, null, null, null);
|
||||
MockInterpreterA.class.getName(), "runner", "path", "localRepo", env, 10 * 1000, null,
|
||||
null, "anonymous", false);
|
||||
final AngularObjectRegistry registry = new AngularObjectRegistry("spark", null);
|
||||
registry.add("name", "DuyHai DOAN", "nodeId", "paragraphId");
|
||||
final InterpreterGroup interpreterGroup = new InterpreterGroup("groupId");
|
||||
|
|
@ -739,7 +742,8 @@ public class RemoteInterpreterTest {
|
|||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
"anonymous",
|
||||
false);
|
||||
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
intpGroup.get("note").add(intp);
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ public class DistributedResourcePoolTest {
|
|||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
"anonymous",
|
||||
false
|
||||
);
|
||||
|
||||
intpGroup1 = new InterpreterGroup("intpGroup1");
|
||||
|
|
@ -90,7 +91,8 @@ public class DistributedResourcePoolTest {
|
|||
10 * 1000,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
"anonymous",
|
||||
false
|
||||
);
|
||||
|
||||
intpGroup2 = new InterpreterGroup("intpGroup2");
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ public class RemoteSchedulerTest implements RemoteInterpreterProcessListener {
|
|||
10 * 1000,
|
||||
this,
|
||||
null,
|
||||
null);
|
||||
"anonymous",
|
||||
false);
|
||||
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
intpGroup.get("note").add(intpA);
|
||||
|
|
@ -172,7 +173,8 @@ public class RemoteSchedulerTest implements RemoteInterpreterProcessListener {
|
|||
10 * 1000,
|
||||
this,
|
||||
null,
|
||||
null);
|
||||
"anonymous",
|
||||
false);
|
||||
|
||||
intpGroup.put("note", new LinkedList<Interpreter>());
|
||||
intpGroup.get("note").add(intpA);
|
||||
|
|
|
|||
|
|
@ -196,7 +196,20 @@ limitations under the License.
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row interpreter" style="margin-top: 5px;">
|
||||
<div class="row interpreter" style="margin-top: 5px;"
|
||||
ng-show="getInterpreterRunningOption(setting.id)=='Per User' && getPerUserOption(setting.id)=='isolated'">
|
||||
<div class="col-md-12">
|
||||
<div class="checkbox remove-margin-top-bottom">
|
||||
<span class="input-group" style="line-height:30px;">
|
||||
<label>
|
||||
<input type="checkbox" style="width:20px" ng-model="setting.option.isUserImpersonate" />
|
||||
User Impersonate
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row interpreter">
|
||||
<div class="col-md-12">
|
||||
<div class="checkbox remove-margin-top-bottom">
|
||||
<span class="input-group" style="line-height:30px;">
|
||||
|
|
|
|||
|
|
@ -327,6 +327,13 @@
|
|||
if (setting.option.setPermission === undefined) {
|
||||
setting.option.setPermission = false;
|
||||
}
|
||||
if (setting.option.isUserImpersonate === undefined) {
|
||||
setting.option.isUserImpersonate = false;
|
||||
}
|
||||
if (!($scope.getInterpreterRunningOption(settingId) === 'Per User' &&
|
||||
$scope.getPerUserOption(settingId) === 'isolated')) {
|
||||
setting.option.isUserImpersonate = false;
|
||||
}
|
||||
if (setting.option.remote === undefined) {
|
||||
// remote always true for now
|
||||
setting.option.remote = true;
|
||||
|
|
|
|||
|
|
@ -313,7 +313,23 @@ limitations under the License.
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row interpreter" style="margin-top: 5px;">
|
||||
|
||||
<div class="row interpreter" style="margin-top: 5px;"
|
||||
ng-show="getInterpreterRunningOption(setting.id)=='Per User' && getPerUserOption(setting.id)=='isolated'">
|
||||
<div class="col-md-12">
|
||||
<div class="checkbox remove-margin-top-bottom">
|
||||
<span class="input-group" style="line-height:30px;">
|
||||
<label>
|
||||
<input type="checkbox" style="width:20px"
|
||||
ng-model="setting.option.isUserImpersonate"
|
||||
ng-disabled="!valueform.$visible" />
|
||||
User Impersonate
|
||||
</label>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row interpreter">
|
||||
<div class="col-md-12">
|
||||
<div class="checkbox remove-margin-top-bottom">
|
||||
<span class="input-group" style="line-height:30px;">
|
||||
|
|
|
|||
|
|
@ -17,11 +17,12 @@
|
|||
angular.module('zeppelinWebApp').controller('LoginCtrl', LoginCtrl);
|
||||
|
||||
LoginCtrl.$inject = ['$scope', '$rootScope', '$http', '$httpParamSerializer', 'baseUrlSrv'];
|
||||
|
||||
function LoginCtrl($scope, $rootScope, $http, $httpParamSerializer, baseUrlSrv) {
|
||||
$scope.SigningIn = false;
|
||||
$scope.loginParams = {};
|
||||
$scope.login = function() {
|
||||
|
||||
$scope.SigningIn = true;
|
||||
$http({
|
||||
method: 'POST',
|
||||
url: baseUrlSrv.getRestApiBase() + '/login',
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
$rootScope.userName = $scope.loginParams.userName;
|
||||
}, function errorCallback(errorResponse) {
|
||||
$scope.loginParams.errorText = 'The username and password that you entered don\'t match.';
|
||||
$scope.SigningIn = false;
|
||||
});
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,8 +41,11 @@ limitations under the License.
|
|||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div>
|
||||
<div class="modal-footer" ng-switch on="SigningIn">
|
||||
<div ng-switch-when="true">
|
||||
<button type="button" class="btn btn-default btn-primary" disabled><i class="fa fa-circle-o-notch fa-spin"></i> Signing In</button>
|
||||
</div>
|
||||
<div ng-switch-default>
|
||||
<button type="button" class="btn btn-default btn-primary" ng-click="login()">Login</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -785,10 +785,10 @@ public class InterpreterFactory implements InterpreterGroupFactory {
|
|||
if (option.isExistingProcess()) {
|
||||
interpreter =
|
||||
connectToRemoteRepl(noteId, info.getClassName(), option.getHost(), option.getPort(),
|
||||
properties);
|
||||
properties, user, option.isUserImpersonate);
|
||||
} else {
|
||||
interpreter = createRemoteRepl(path, key, info.getClassName(), properties,
|
||||
interpreterSetting.getId());
|
||||
interpreterSetting.getId(), user, option.isUserImpersonate());
|
||||
}
|
||||
} else {
|
||||
interpreter = createRepl(interpreterSetting.getPath(), info.getClassName(), properties);
|
||||
|
|
@ -1109,17 +1109,18 @@ public class InterpreterFactory implements InterpreterGroupFactory {
|
|||
}
|
||||
|
||||
private Interpreter connectToRemoteRepl(String noteId, String className, String host, int port,
|
||||
Properties property) {
|
||||
Properties property, String userName, Boolean isUserImpersonate) {
|
||||
int connectTimeout = conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_CONNECT_TIMEOUT);
|
||||
int maxPoolSize = conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_MAX_POOL_SIZE);
|
||||
LazyOpenInterpreter intp = new LazyOpenInterpreter(
|
||||
new RemoteInterpreter(property, noteId, className, host, port, connectTimeout, maxPoolSize,
|
||||
remoteInterpreterProcessListener, appEventListener, remoteWorksController));
|
||||
remoteInterpreterProcessListener, appEventListener, userName, isUserImpersonate));
|
||||
return intp;
|
||||
}
|
||||
|
||||
private Interpreter createRemoteRepl(String interpreterPath, String noteId, String className,
|
||||
Properties property, String interpreterSettingId) {
|
||||
Properties property, String interpreterSettingId, String userName,
|
||||
Boolean isUserImpersonate) {
|
||||
int connectTimeout = conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_CONNECT_TIMEOUT);
|
||||
String localRepoPath = conf.getInterpreterLocalRepoPath() + "/" + interpreterSettingId;
|
||||
int maxPoolSize = conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_MAX_POOL_SIZE);
|
||||
|
|
@ -1127,7 +1128,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
|
|||
RemoteInterpreter remoteInterpreter =
|
||||
new RemoteInterpreter(property, noteId, className, conf.getInterpreterRemoteRunnerPath(),
|
||||
interpreterPath, localRepoPath, connectTimeout, maxPoolSize,
|
||||
remoteInterpreterProcessListener, appEventListener, remoteWorksController);
|
||||
remoteInterpreterProcessListener, appEventListener, userName, isUserImpersonate);
|
||||
remoteInterpreter.addEnv(env);
|
||||
|
||||
return new LazyOpenInterpreter(remoteInterpreter);
|
||||
|
|
@ -1423,7 +1424,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
|
|||
InterpreterGroup interpreterGroup = createInterpreterGroup("dev", option);
|
||||
|
||||
devInterpreter = connectToRemoteRepl("dev", DevInterpreter.class.getName(), "localhost",
|
||||
ZeppelinDevServer.DEFAULT_TEST_INTERPRETER_PORT, new Properties());
|
||||
ZeppelinDevServer.DEFAULT_TEST_INTERPRETER_PORT, new Properties(), "anonymous", false);
|
||||
|
||||
LinkedList<Interpreter> intpList = new LinkedList<>();
|
||||
intpList.add(devInterpreter);
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ public class Paragraph extends Job implements Serializable, Cloneable {
|
|||
}
|
||||
|
||||
private boolean isValidInterpreter(String replName) {
|
||||
return factory.getInterpreter("",
|
||||
return factory.getInterpreter(user,
|
||||
note.getId(), replName) != null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue