Merge remote-tracking branch 'origin/master' into ZEPPELIN-2403

This commit is contained in:
Tinkoff DWH 2017-05-11 09:24:05 +05:00
commit 76a9808307
69 changed files with 355 additions and 364 deletions

33
.appveyor.yml Normal file
View file

@ -0,0 +1,33 @@
#
# 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.
#
version: '1.0.0-dev.{build}'
shallow_clone: true
build: off
os:
- Visual Studio 2015
install:
- echo "Install"
build_script:
- echo "Build"

View file

@ -46,8 +46,15 @@ matrix:
env: SCALA_VER="2.11" SPARK_VER="2.0.2" HADOOP_VER="2.6" PROFILE="-Prat" BUILD_FLAG="clean" TEST_FLAG="org.apache.rat:apache-rat-plugin:check" TEST_PROJECTS=""
# Test core modules
#
# Several tests were excluded from this configuration due to the following issues:
# HeliumBundleFactoryTest - https://issues.apache.org/jira/browse/ZEPPELIN-2469
# HeliumApplicationFactoryTest - https://issues.apache.org/jira/browse/ZEPPELIN-2470
# NotebookTest - https://issues.apache.org/jira/browse/ZEPPELIN-2471
# ZeppelinRestApiTest - https://issues.apache.org/jira/browse/ZEPPELIN-2473
# After issues are fixed these tests need to be included back by removing them from the "-Dtests.to.exclude" property
- jdk: "oraclejdk7"
env: SCALA_VER="2.11" SPARK_VER="2.1.0" HADOOP_VER="2.6" PROFILE="-Pweb-ci -Pscalding -Phelium-dev -Pexamples -Pscala-2.11" BUILD_FLAG="package -Pbuild-distr -DskipRat" TEST_FLAG="verify -Pusing-packaged-distr -DskipRat" MODULES="-pl ${INTERPRETERS}" TEST_PROJECTS="-Dtest='!ZeppelinSparkClusterTest,!org.apache.zeppelin.spark.*' -DfailIfNoTests=false"
env: SCALA_VER="2.11" SPARK_VER="2.1.0" HADOOP_VER="2.6" PROFILE="-Pweb-ci -Pscalding -Phelium-dev -Pexamples -Pscala-2.11" BUILD_FLAG="package -Pbuild-distr -DskipRat" TEST_FLAG="verify -Pusing-packaged-distr -DskipRat" MODULES="-pl ${INTERPRETERS}" TEST_PROJECTS="-Dtests.to.exclude=**/ZeppelinSparkClusterTest.java,**/org.apache.zeppelin.spark.*,**/HeliumBundleFactoryTest.java,**/HeliumApplicationFactoryTest.java,**/NotebookTest.java,**/ZeppelinRestApiTest.java -DfailIfNoTests=false"
# Test selenium with spark module for 1.6.3
- jdk: "oraclejdk7"

View file

@ -369,4 +369,12 @@
<description>Enable directory listings on server.</description>
</property>
<!--
<property>
<name>zeppelin.server.jetty.name</name>
<value>Jetty(7.6.0.v20120127)</value>
<description>Hardcoding Application Server name to Prevent Fingerprinting</description>
</property>
-->
</configuration>

View file

@ -18,8 +18,8 @@
#
usage() {
echo "usage) $0 [Old version] [New version]"
echo " ex. $0 0.7.0-SNAPSHOT 0.7.0"
echo "usage) $0 [OLD version] [NEW version]"
echo " ex. $0 0.8.0-SNAPSHOT 0.8.0"
exit 1
}
@ -58,6 +58,9 @@ sed -i '' 's/-'"${FROM_VERSION}"'.jar",/-'"${TO_VERSION}"'.jar",/g' zeppelin-exa
sed -i '' 's/"version": "'"${FROM_VERSION}"'",/"version": "'"${TO_VERSION}"'",/g' zeppelin-web/src/app/tabledata/package.json
sed -i '' 's/"version": "'"${FROM_VERSION}"'",/"version": "'"${TO_VERSION}"'",/g' zeppelin-web/src/app/visualization/package.json
# Change version in Dockerfile
sed -i '' 's/Z_VERSION="'"${FROM_VERSION}"'"/Z_VERSION="'"${TO_VERSION}"'"/g' scripts/docker/zeppelin/bin/Dockerfile
# When preparing new dev version from release tag, doesn't need to change docs version
if is_dev_version "${FROM_VERSION}" || ! is_dev_version "${TO_VERSION}"; then
# When prepare new rc for the maintenance release

View file

@ -112,7 +112,7 @@ import AngularElem._
### Display Element
```scala
// automatically convert to string and print with %angular display system directive in front.
<div><div>.display
<div></div>.display
```
### Event Handler
```scala

View file

@ -19,7 +19,7 @@ limitations under the License.
-->
{% include JB/setup %}
# Apache Zeppelin Releases Docker Images
# Docker Image for Apache Zeppelin Releases
<div id="toc"></div>
@ -34,7 +34,7 @@ You need to [install docker](https://docs.docker.com/engine/installation/) on yo
### Running docker image
```
docker run -p 8080:8080 --name zeppelin zeppelin:<release-version>
docker run -p 8080:8080 --rm --name zeppelin apache/zeppelin:<release-version>
```
* Zeppelin will run at `http://localhost:8080`.
@ -42,20 +42,20 @@ docker run -p 8080:8080 --name zeppelin zeppelin:<release-version>
If you want to specify `logs` and `notebook` dir,
```
docker run -p 8080:8080 \
docker run -p 8080:8080 --rm \
-v $PWD/logs:/logs \
-v $PWD/notebook:/notebook \
-e ZEPPELIN_LOG_DIR='/logs' \
-e ZEPPELIN_NOTEBOOK_DIR='/notebook' \
--name zeppelin zeppelin:<release-version> # e.g '0.7.1'
--name zeppelin apache/zeppelin:<release-version> # e.g '0.7.1'
```
### Building dockerfile locally
```
cd $ZEPPELIN_HOME
cd scripts/docker/zeppelin
cd scripts/docker/zeppelin/bin
./create-dockerfile.sh <release-version> # e.g '0.7.1'
docker build -t my-zeppelin:my-tag ./
```

View file

@ -146,7 +146,7 @@ Congratulations, you have successfully installed Apache Zeppelin! Here are few s
* Manage your [notebook permission](../security/notebook_authorization.html).
* For more informations, go to **More** -> **Security** section.
#### Other useful informations ...
#### Other useful information ...
* Learn how [Display System](../displaysystem/basicdisplaysystem.html) works.
* Use [Service Manager](#start-apache-zeppelin-with-a-service-manager) to start Zeppelin.
* If you're using previous version please see [Upgrade Zeppelin version](./upgrade.html).

View file

@ -171,7 +171,7 @@ There are more JDBC interpreter properties you can specify like below.
</tr>
<tr>
<td>zeppelin.jdbc.auth.kerberos.proxy.enable</td>
     <td>When auth type is Kerberos, enable/disable Kerberos proxy with the login user to get the connection. Default value is true.</td>
<td>When auth type is Kerberos, enable/disable Kerberos proxy with the login user to get the connection. Default value is true.</td>
</tr>
<tr>
<td>default.jceks.file</td>
@ -202,7 +202,7 @@ To bind the interpreters created in the interpreter setting page, click the gear
<img src="../assets/themes/zeppelin/img/docs-img/click_interpreter_binding_button.png" width="600px" />
Select(blue) or deselect(white) the interpreter buttons depending on your use cases.
Select(blue) or deselect(white) the interpreter buttons depending on your use cases.
If you need to use more than one interpreter in the notebook, activate several buttons.
Don't forget to click `Save` button, or you will face `Interpreter *** is not found` error.
@ -285,7 +285,7 @@ An example settings of interpreter for the two data sources, each of which has i
</table>
##### Usage
Test of execution *precode* for each data source.
Test of execution *precode* for each data source.
```sql
%jdbc
@ -480,7 +480,7 @@ Here are some examples you can refer to. Including the below connectors, you can
[Maven Repository: com.amazonaws:aws-java-sdk-redshift](https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-redshift)
### Apache Hive
### Apache Hive
<img src="../assets/themes/zeppelin/img/docs-img/hive_setting.png" width="600px" />
@ -507,12 +507,11 @@ Here are some examples you can refer to. Including the below connectors, you can
<td>hive_password</td>
</tr>
<tr>
<td>hive.proxy.user</td>
<td>true or false</td>
<td>default.proxy.user.property</td>
<td>Example value: hive.server2.proxy.user</td>
</tr>
</table>
Connection to Hive JDBC with a proxy user can be disabled with `hive.proxy.user` property (set to true by default)
[Apache Hive 1 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
[Apache Hive 2 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
@ -534,6 +533,44 @@ Connection to Hive JDBC with a proxy user can be disabled with `hive.proxy.user`
[Maven Repository : org.apache.hive:hive-jdbc](https://mvnrepository.com/artifact/org.apache.hive/hive-jdbc)
##### Impersonation
When Zeppelin server is running with authentication enabled, then the interpreter can utilize Hive's user proxy feature i.e. send extra parameter for creating and running a session ("hive.server2.proxy.user=": "${loggedInUser}"). This is particularly useful when multiple users are sharing a notebook.
To enable this set following:
- `zeppelin.jdbc.auth.type` as `SIMPLE` or `KERBEROS` (if required) in the interpreter setting.
- `${prefix}.proxy.user.property` as `hive.server2.proxy.user`
##### Sample configuration
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>hive.driver</td>
<td>org.apache.hive.jdbc.HiveDriver</td>
</tr>
<tr>
<td>hive.password</td>
<td></td>
</tr>
<tr>
<td>hive.url</td>
<td>jdbc:hive2://hive-server-host:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=hiveserver2</td>
</tr>
<tr>
<td>hive.proxy.user.property</td>
<td>hive.server2.proxy.user</td>
</tr>
<tr>
<td>zeppelin.jdbc.auth.type</td>
<td>SIMPLE</td>
</tr>
</table>
### Apache Phoenix
Phoenix supports `thick` and `thin` connection types:

View file

@ -70,7 +70,7 @@ For multi-selection, you can create a checkbox form using `${checkbox:formName=d
<img src="../assets/themes/zeppelin/img/screenshots/form_checkbox.png">
Besides, you can specify the delimiter using `${checkbox(delimiter):formName=...}`:
You can specify the delimiter using `${checkbox(delimiter):formName=...}`:
<img src="../assets/themes/zeppelin/img/screenshots/form_checkbox_delimiter.png">
@ -84,9 +84,9 @@ Even if you uncheck this option, still you can run it by pressing `Enter`.
## Creates Programmatically
Some language backend uses programmatic way to create form. For example [ZeppelinContext](../interpreter/spark.html#zeppelincontext) provides form creation API
Some language backends can programmatically create forms. For example [ZeppelinContext](../interpreter/spark.html#zeppelincontext) provides a form creation API
Here're some examples.
Here are some examples:
### Text input form
<div class="codetabs">

View file

@ -25,7 +25,7 @@ limitations under the License.
## Main home
The first time you connect to Zeppelin, you'll land at the main page similar to the below screen capture.
The first time you connect to Zeppelin ([default installations start on http://localhost:8080](http://localhost:8080/)), you'll land at the main page similar to the below screen capture.
<img src="../assets/themes/zeppelin/img/ui-img/homepage.png" />

View file

@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@ -179,10 +178,6 @@ public class JDBCInterpreter extends Interpreter {
}
logger.debug("JDBC PropretiesMap: {}", basePropretiesMap);
if (!isEmpty(property.getProperty("zeppelin.jdbc.auth.type"))) {
JDBCSecurityImpl.createSecureConfiguration(property);
}
setMaxLineResults();
}
@ -355,36 +350,25 @@ public class JDBCInterpreter extends Interpreter {
} else {
UserGroupInformation.AuthenticationMethod authType = JDBCSecurityImpl.getAuthtype(property);
final String connectionUrl = appendProxyUserToURL(url, user, propertyKey);
JDBCSecurityImpl.createSecureConfiguration(property, authType);
switch (authType) {
case KERBEROS:
if (user == null || "false".equalsIgnoreCase(
property.getProperty("zeppelin.jdbc.auth.kerberos.proxy.enable"))) {
connection = getConnectionFromPool(url, user, propertyKey, properties);
property.getProperty("zeppelin.jdbc.auth.kerberos.proxy.enable"))) {
connection = getConnectionFromPool(connectionUrl, user, propertyKey, properties);
} else {
if (url.trim().startsWith("jdbc:hive")) {
StringBuilder connectionUrl = new StringBuilder(url);
Integer lastIndexOfUrl = connectionUrl.indexOf("?");
if (lastIndexOfUrl == -1) {
lastIndexOfUrl = connectionUrl.length();
}
boolean hasProxyUser = property.containsKey("hive.proxy.user");
if (!hasProxyUser || !property.getProperty("hive.proxy.user").equals("false")){
logger.debug("Using hive proxy user");
connectionUrl.insert(lastIndexOfUrl, ";hive.server2.proxy.user=" + user + ";");
}
connection = getConnectionFromPool(connectionUrl.toString(),
user, propertyKey, properties);
if (basePropretiesMap.get(propertyKey).containsKey("proxy.user.property")) {
connection = getConnectionFromPool(connectionUrl, user, propertyKey, properties);
} else {
UserGroupInformation ugi = null;
try {
ugi = UserGroupInformation.createProxyUser(
user, UserGroupInformation.getCurrentUser());
user, UserGroupInformation.getCurrentUser());
} catch (Exception e) {
logger.error("Error in getCurrentUser", e);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(e.getMessage()).append("\n");
stringBuilder.append(e.getCause());
throw new InterpreterException(stringBuilder.toString());
throw new InterpreterException("Error in getCurrentUser", e);
}
final String poolKey = propertyKey;
@ -392,28 +376,48 @@ public class JDBCInterpreter extends Interpreter {
connection = ugi.doAs(new PrivilegedExceptionAction<Connection>() {
@Override
public Connection run() throws Exception {
return getConnectionFromPool(url, user, poolKey, properties);
return getConnectionFromPool(connectionUrl, user, poolKey, properties);
}
});
} catch (Exception e) {
logger.error("Error in doAs", e);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(e.getMessage()).append("\n");
stringBuilder.append(e.getCause());
throw new InterpreterException(stringBuilder.toString());
throw new InterpreterException("Error in doAs", e);
}
}
}
break;
default:
connection = getConnectionFromPool(url, user, propertyKey, properties);
connection = getConnectionFromPool(connectionUrl, user, propertyKey, properties);
}
}
return connection;
}
private String appendProxyUserToURL(String url, String user, String propertyKey) {
StringBuilder connectionUrl = new StringBuilder(url);
if (user != null && !user.equals("anonymous") &&
basePropretiesMap.get(propertyKey).containsKey("proxy.user.property")) {
Integer lastIndexOfUrl = connectionUrl.indexOf("?");
if (lastIndexOfUrl == -1) {
lastIndexOfUrl = connectionUrl.length();
}
logger.info("Using proxy user as :" + user);
logger.info("Using proxy property for user as :" +
basePropretiesMap.get(propertyKey).getProperty("proxy.user.property"));
connectionUrl.insert(lastIndexOfUrl, ";" +
basePropretiesMap.get(propertyKey).getProperty("proxy.user.property") + "=" + user + ";");
} else if (user != null && !user.equals("anonymous") && url.contains("hive")) {
logger.warn("User impersonation for hive has changed please refer: http://zeppelin.apache" +
".org/docs/latest/interpreter/jdbc.html#apache-hive");
}
return connectionUrl.toString();
}
private String getPassword(Properties properties) throws IOException {
if (isNotEmpty(properties.getProperty(PASSWORD_KEY))) {
return properties.getProperty(PASSWORD_KEY);

View file

@ -38,9 +38,8 @@ public class JDBCSecurityImpl {
/***
* @param properties
*/
public static void createSecureConfiguration(Properties properties) {
AuthenticationMethod authType = getAuthtype(properties);
public static void createSecureConfiguration(Properties properties,
AuthenticationMethod authType) {
switch (authType) {
case KERBEROS:
Configuration conf = new

View file

@ -49,7 +49,6 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ConcurrentHashMap;
@ -57,9 +56,9 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Base class for livy interpreters.
*/
public abstract class BaseLivyInterprereter extends Interpreter {
public abstract class BaseLivyInterpreter extends Interpreter {
protected static final Logger LOGGER = LoggerFactory.getLogger(BaseLivyInterprereter.class);
protected static final Logger LOGGER = LoggerFactory.getLogger(BaseLivyInterpreter.class);
private static Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
private static String SESSION_NOT_FOUND_PATTERN = "\"Session '\\d+' not found.\"";
@ -68,7 +67,6 @@ public abstract class BaseLivyInterprereter extends Interpreter {
private int sessionCreationTimeout;
private int pullStatusInterval;
protected boolean displayAppInfo;
private AtomicBoolean sessionExpired = new AtomicBoolean(false);
protected LivyVersion livyVersion;
private RestTemplate restTemplate;
@ -77,7 +75,7 @@ public abstract class BaseLivyInterprereter extends Interpreter {
private ConcurrentHashMap<String, Integer> paragraphId2StmtProgressMap =
new ConcurrentHashMap<>();
public BaseLivyInterprereter(Properties property) {
public BaseLivyInterpreter(Properties property) {
super(property);
this.livyURL = property.getProperty("zeppelin.livy.url");
this.displayAppInfo = Boolean.parseBoolean(

View file

@ -17,16 +17,6 @@
package org.apache.zeppelin.livy;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

View file

@ -23,7 +23,7 @@ import java.util.Properties;
/**
* Base class for PySpark Interpreter
*/
public abstract class LivyPySparkBaseInterpreter extends BaseLivyInterprereter {
public abstract class LivyPySparkBaseInterpreter extends BaseLivyInterpreter {
public LivyPySparkBaseInterpreter(Properties property) {
super(property);

View file

@ -17,16 +17,6 @@
package org.apache.zeppelin.livy;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

View file

@ -17,23 +17,12 @@
package org.apache.zeppelin.livy;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
/**
* Livy Spark interpreter for Zeppelin.
*/
public class LivySparkInterpreter extends BaseLivyInterprereter {
public class LivySparkInterpreter extends BaseLivyInterpreter {
public LivySparkInterpreter(Properties property) {
super(property);

View file

@ -17,23 +17,13 @@
package org.apache.zeppelin.livy;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
/**
* Livy PySpark interpreter for Zeppelin.
*/
public class LivySparkRInterpreter extends BaseLivyInterprereter {
public class LivySparkRInterpreter extends BaseLivyInterpreter {
public LivySparkRInterpreter(Properties property) {
super(property);

View file

@ -30,7 +30,7 @@ import java.util.Properties;
/**
* Livy SparkSQL Interpreter for Zeppelin.
*/
public class LivySparkSQLInterpreter extends BaseLivyInterprereter {
public class LivySparkSQLInterpreter extends BaseLivyInterpreter {
public static final String ZEPPELIN_LIVY_SPARK_SQL_FIELD_TRUNCATE =
"zeppelin.livy.spark.sql.field.truncate";

View file

@ -761,7 +761,7 @@ public class LivyInterpreterIT {
}
}
private boolean isSpark2(BaseLivyInterprereter interpreter, InterpreterContext context) {
private boolean isSpark2(BaseLivyInterpreter interpreter, InterpreterContext context) {
InterpreterResult result = null;
if (interpreter instanceof LivySparkRInterpreter) {
result = interpreter.interpret("sparkR.session()", context);

View file

@ -134,6 +134,9 @@
<PermGen>64m</PermGen>
<MaxPermGen>512m</MaxPermGen>
<!-- to be able to exclude some tests using command line -->
<tests.to.exclude/>
</properties>
<dependencyManagement>
@ -555,6 +558,9 @@
<version>${plugin.surefire.version}</version>
<configuration combine.children="append">
<argLine>-Xmx2g -Xms1g -Dfile.encoding=UTF-8</argLine>
<excludes>
<exclude>${tests.to.exclude}</exclude>
</excludes>
</configuration>
<!-- <excludes> <exclude>**/itest/**</exclude> </excludes> <executions>
<execution> <id>surefire-itest</id> <phase>integration-test</phase> <goals>

View file

@ -1,37 +0,0 @@
# 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.
FROM zeppelin:base
MAINTAINER Apache Software Foundation <dev@zeppelin.apache.org>
ENV Z_VERSION="0.6.2"
ENV LOG_TAG="[ZEPPELIN_${Z_VERSION}]:" \
Z_HOME="/zeppelin"
RUN echo "$LOG_TAG Download Zeppelin binary" && \
wget -O /tmp/zeppelin-${Z_VERSION}-bin-all.tgz http://archive.apache.org/dist/zeppelin/zeppelin-${Z_VERSION}/zeppelin-${Z_VERSION}-bin-all.tgz && \
tar -zxvf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
rm -rf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
mv /zeppelin-${Z_VERSION}-bin-all ${Z_HOME}
RUN echo "$LOG_TAG Cleanup" && \
apt-get autoclean && \
apt-get clean
EXPOSE 8080
WORKDIR ${Z_HOME}
CMD ["bin/zeppelin.sh"]

View file

@ -1,37 +0,0 @@
# 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.
FROM zeppelin:base
MAINTAINER Apache Software Foundation <dev@zeppelin.apache.org>
ENV Z_VERSION="0.7.0"
ENV LOG_TAG="[ZEPPELIN_${Z_VERSION}]:" \
Z_HOME="/zeppelin"
RUN echo "$LOG_TAG Download Zeppelin binary" && \
wget -O /tmp/zeppelin-${Z_VERSION}-bin-all.tgz http://archive.apache.org/dist/zeppelin/zeppelin-${Z_VERSION}/zeppelin-${Z_VERSION}-bin-all.tgz && \
tar -zxvf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
rm -rf /zeppelin-${Z_VERSION}-bin-all.tgz && \
mv /zeppelin-${Z_VERSION}-bin-all ${Z_HOME}
RUN echo "$LOG_TAG Cleanup" && \
apt-get autoclean && \
apt-get clean
EXPOSE 8080
WORKDIR ${Z_HOME}
CMD ["bin/zeppelin.sh"]

View file

@ -1,37 +0,0 @@
# 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.
FROM zeppelin:base
MAINTAINER Apache Software Foundation <dev@zeppelin.apache.org>
ENV Z_VERSION="0.7.1"
ENV LOG_TAG="[ZEPPELIN_${Z_VERSION}]:" \
Z_HOME="/zeppelin"
RUN echo "$LOG_TAG Download Zeppelin binary" && \
wget -O /tmp/zeppelin-${Z_VERSION}-bin-all.tgz http://archive.apache.org/dist/zeppelin/zeppelin-${Z_VERSION}/zeppelin-${Z_VERSION}-bin-all.tgz && \
tar -zxvf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
rm -rf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
mv /zeppelin-${Z_VERSION}-bin-all ${Z_HOME}
RUN echo "$LOG_TAG Cleanup" && \
apt-get autoclean && \
apt-get clean
EXPOSE 8080
WORKDIR ${Z_HOME}
CMD ["bin/zeppelin.sh"]

View file

@ -1,37 +0,0 @@
# 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.
FROM zeppelin:base
MAINTAINER Apache Software Foundation <dev@zeppelin.apache.org>
ENV Z_VERSION="0.0.0"
ENV LOG_TAG="[ZEPPELIN_${Z_VERSION}]:" \
Z_HOME="/zeppelin"
RUN echo "$LOG_TAG Download Zeppelin binary" && \
wget -O /tmp/zeppelin-${Z_VERSION}-bin-all.tgz http://archive.apache.org/dist/zeppelin/zeppelin-${Z_VERSION}/zeppelin-${Z_VERSION}-bin-all.tgz && \
tar -zxvf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
rm -rf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
mv /zeppelin-${Z_VERSION}-bin-all ${Z_HOME}
RUN echo "$LOG_TAG Cleanup" && \
apt-get autoclean && \
apt-get clean
EXPOSE 8080
WORKDIR ${Z_HOME}
CMD ["bin/zeppelin.sh"]

View file

@ -16,7 +16,10 @@
FROM ubuntu:16.04
MAINTAINER Apache Software Foundation <dev@zeppelin.apache.org>
ENV LOG_TAG="[ZEPPELIN_BASE]:" \
# `Z_VERSION` will be updated by `dev/change_zeppelin_version.sh`
ENV Z_VERSION="0.8.0-SNAPSHOT"
ENV LOG_TAG="[ZEPPELIN_${Z_VERSION}]:" \
Z_HOME="/zeppelin" \
LANG=en_US.UTF-8 \
LC_ALL=en_US.UTF-8
@ -86,5 +89,18 @@ RUN echo "$LOG_TAG Install R related packages" && \
R -e "install.packages('Rcpp', repos='http://cran.us.r-project.org')" && \
Rscript -e "library('devtools'); library('Rcpp'); install_github('ramnathv/rCharts')"
RUN echo "$LOG_TAG Download Zeppelin binary" && \
wget -O /tmp/zeppelin-${Z_VERSION}-bin-all.tgz http://archive.apache.org/dist/zeppelin/zeppelin-${Z_VERSION}/zeppelin-${Z_VERSION}-bin-all.tgz && \
tar -zxvf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
rm -rf /tmp/zeppelin-${Z_VERSION}-bin-all.tgz && \
mv /zeppelin-${Z_VERSION}-bin-all ${Z_HOME}
RUN echo "$LOG_TAG Cleanup" && \
apt-get autoclean && \
apt-get clean
EXPOSE 8080
ENTRYPOINT [ "/usr/bin/tini", "--" ]
CMD [ "/bin/bash" ]
WORKDIR ${Z_HOME}
CMD ["bin/zeppelin.sh"]

View file

@ -1,51 +0,0 @@
#!/usr/bin/env bash
# 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.
#
if [ $# -lt 1 ];
then
echo "USAGE: $0 version"
echo "* version: 0.6.2 (released zeppelin binary version)"
exit 1
fi
TAG="[CREATE-DOCKERFILE]"
VERSION=$1
BASE_DIR="./base/"
TEMPLATE_DOCKERFILE="./bin-template/Dockerfile"
if [ ! -d "$BASE_DIR" ]; then
echo "${TAG} Base Directory doesn't exist: ${BASE_DIR}"
exit 1
fi
TARGET_DIR="${VERSION}"
BASE_IMAGE_TAG="base"
if [ ! -d "$TARGET_DIR" ]; then
echo "${TAG} Creating Directory: ${TARGET_DIR}"
mkdir -p ${TARGET_DIR}
echo "${TAG} Copying File: ${TARGET_DIR}/Dockerfile"
cp ${TEMPLATE_DOCKERFILE} ${TARGET_DIR}/Dockerfile
echo "${TAG} Set Version: ${VERSION}"
sed -i '' -e "s/Z_VERSION=\"0.0.0\"/Z_VERSION=\"${VERSION}\"/g" ${TARGET_DIR}/Dockerfile
else
echo "${TAG} Directory already exists: ${TARGET_DIR}"
fi

View file

@ -131,10 +131,10 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
// create AngularFunction in current paragraph
val functionName = eventName.replaceAll("-", "_") + "_" + uniqueId
val elem = this % Attribute(None, eventName,
Text(s"${functionName}=$$event.timeStamp"),
Text(s"${functionName}=${functionName} + 1"),
Null)
val angularObject = addAngularObject(functionName, "")
val angularObject = addAngularObject(functionName, 0)
angularObject.addWatcher(new AngularObjectWatcher(interpreterContext) {
override def watch(oldObject: scala.Any, newObject: scala.Any, context: InterpreterContext)

View file

@ -31,4 +31,8 @@ public class InterpreterException extends RuntimeException {
super(m);
}
public InterpreterException(String msg, Throwable t) {
super(msg, t);
}
}

View file

@ -218,7 +218,7 @@ public class RemoteInterpreterServer
private void setSystemProperty(Properties properties) {
for (Object key : properties.keySet()) {
if (!RemoteInterpreter.isEnvString((String) key)) {
if (!RemoteInterpreterUtils.isEnvString((String) key)) {
String value = properties.getProperty((String) key);
if (value == null || value.isEmpty()) {
System.clearProperty((String) key);

View file

@ -17,7 +17,6 @@
package org.apache.zeppelin.interpreter.remote;
import org.apache.zeppelin.interpreter.InterpreterGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -73,4 +72,12 @@ public class RemoteInterpreterUtils {
}
return settingId;
}
public static boolean isEnvString(String key) {
if (key == null || key.length() == 0) {
return false;
}
return key.matches("^[A-Z_0-9]*");
}
}

View file

@ -19,7 +19,6 @@ package org.apache.zeppelin.resource;
import com.google.gson.Gson;
import org.apache.zeppelin.interpreter.InterpreterGroup;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterManagedProcess;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterProcess;
import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService;
import org.slf4j.Logger;

View file

@ -20,7 +20,6 @@ package org.apache.zeppelin.scheduler;
import org.apache.thrift.TException;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterManagedProcess;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterProcess;
import org.apache.zeppelin.interpreter.thrift.RemoteInterpreterService.Client;
import org.apache.zeppelin.scheduler.Job.Status;

View file

@ -0,0 +1,43 @@
package org.apache.zeppelin.interpreter;
import java.util.Properties;
/**
*
*/
public class DummyInterpreter extends Interpreter {
public DummyInterpreter(Properties property) {
super(property);
}
@Override
public void open() {
}
@Override
public void close() {
}
@Override
public InterpreterResult interpret(String st, InterpreterContext context) {
return null;
}
@Override
public void cancel(InterpreterContext context) {
}
@Override
public FormType getFormType() {
return null;
}
@Override
public int getProgress(InterpreterContext context) {
return 0;
}
}

View file

@ -19,7 +19,6 @@ package org.apache.zeppelin.interpreter;
import java.util.Properties;
import org.apache.zeppelin.interpreter.remote.mock.MockInterpreterA;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.junit.Test;
@ -31,7 +30,7 @@ public class InterpreterTest {
public void testDefaultProperty() {
Properties p = new Properties();
p.put("p1", "v1");
MockInterpreterA intp = new MockInterpreterA(p);
Interpreter intp = new DummyInterpreter(p);
assertEquals(1, intp.getProperty().size());
assertEquals("v1", intp.getProperty().get("p1"));
@ -42,7 +41,7 @@ public class InterpreterTest {
public void testOverriddenProperty() {
Properties p = new Properties();
p.put("p1", "v1");
MockInterpreterA intp = new MockInterpreterA(p);
Interpreter intp = new DummyInterpreter(p);
Properties overriddenProperty = new Properties();
overriddenProperty.put("p1", "v2");
intp.setProperty(overriddenProperty);
@ -74,7 +73,7 @@ public class InterpreterTest {
Properties p = new Properties();
p.put("p1", "replName #{noteId}, #{paragraphTitle}, #{paragraphId}, #{paragraphText}, #{replName}, #{noteId}, #{user}," +
" #{authenticationInfo}");
MockInterpreterA intp = new MockInterpreterA(p);
Interpreter intp = new DummyInterpreter(p);
intp.setUserName(user);
String actual = intp.getProperty("p1");
InterpreterContext.remove();

View file

@ -74,7 +74,11 @@ public class LoginRestApi {
try {
UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
// token.setRememberMe(true);
currentUser.getSession().stop();
currentUser.getSession(true);
currentUser.login(token);
HashSet<String> roles = SecurityUtils.getRoles();
String principal = SecurityUtils.getPrincipal();
String ticket;

View file

@ -193,6 +193,9 @@ public class ZeppelinServer extends Application {
LOG.info("Starting zeppelin server");
try {
jettyWebServer.start(); //Instantiates ZeppelinServer
if (conf.getJettyName() != null) {
org.eclipse.jetty.http.HttpGenerator.setJettyVersion(conf.getJettyName());
}
} catch (Exception e) {
LOG.error("Error while running jettyServer", e);
System.exit(-1);

View file

@ -1742,10 +1742,10 @@ public class NotebookServer extends WebSocketServlet
}
private void addNewParagraphIfLastParagraphIsExecuted(Note note, Paragraph p) {
// if it's the last paragraph and empty, let's add a new one
// if it's the last paragraph and not empty, let's add a new one
boolean isTheLastParagraph = note.isLastParagraph(p.getId());
if (!(p.getText().trim().equals(p.getMagic()) ||
Strings.isNullOrEmpty(p.getText())) &&
if (!(Strings.isNullOrEmpty(p.getText()) ||
p.getText().trim().equals(p.getMagic())) &&
isTheLastParagraph) {
Paragraph newPara = note.addNewParagraph(p.getAuthenticationInfo());
broadcastNewParagraph(note, newPara);

View file

@ -60,11 +60,13 @@ public class SecurityUtils {
public static Boolean isValidOrigin(String sourceHost, ZeppelinConfiguration conf)
throws UnknownHostException, URISyntaxException {
if (sourceHost == null || sourceHost.isEmpty()) {
return false;
String sourceUriHost = "";
if (sourceHost != null && !sourceHost.isEmpty()) {
sourceUriHost = new URI(sourceHost).getHost();
sourceUriHost = (sourceUriHost == null) ? "" : sourceUriHost.toLowerCase();
}
String sourceUriHost = new URI(sourceHost).getHost();
sourceUriHost = (sourceUriHost == null) ? "" : sourceUriHost.toLowerCase();
sourceUriHost = sourceUriHost.toLowerCase();
String currentHost = InetAddress.getLocalHost().getHostName().toLowerCase();

View file

@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import org.apache.commons.io.FileUtils;
@ -146,14 +147,20 @@ public class AuthenticationIT extends AbstractZeppelinIT {
}
}
private void logoutUser(String userName) {
private void logoutUser(String userName) throws URISyntaxException {
ZeppelinITUtils.sleep(500, false);
driver.findElement(By.xpath("//div[contains(@class, 'navbar-collapse')]//li[contains(.,'" +
userName + "')]")).click();
ZeppelinITUtils.sleep(500, false);
driver.findElement(By.xpath("//div[contains(@class, 'navbar-collapse')]//li[contains(.,'" +
userName + "')]//a[@ng-click='navbar.logout()']")).click();
ZeppelinITUtils.sleep(5000, false);
ZeppelinITUtils.sleep(2000, false);
if (driver.findElement(By.xpath("//*[@id='loginModal']//div[contains(@class, 'modal-header')]/button"))
.isDisplayed()) {
driver.findElement(By.xpath("//*[@id='loginModal']//div[contains(@class, 'modal-header')]/button")).click();
}
driver.get(new URI(driver.getCurrentUrl()).resolve("/#/").toString());
ZeppelinITUtils.sleep(500, false);
}
// @Test

View file

@ -70,6 +70,12 @@ public class SecurityUtilsTest {
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site.xml"))));
}
@Test
public void nullOriginWithStar() throws URISyntaxException, UnknownHostException, ConfigurationException {
assertTrue(SecurityUtils.isValidOrigin(null,
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site-star.xml"))));
}
@Test
public void emptyOrigin() throws URISyntaxException, UnknownHostException, ConfigurationException {
assertFalse(SecurityUtils.isValidOrigin("",

View file

@ -131,6 +131,8 @@ limitations under the License.
ng-hide="viewOnly"
ng-click="checkpointNote(note.checkpoint.message)"
style="margin-left: 4px;"
tooltip-append-to-body="true"
tooltip-class="revisionTooltip"
tooltip-placement="bottom" uib-tooltip="Commit this note">Commit
</button>
</div>

View file

@ -483,20 +483,23 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
}
$scope.$on('addParagraph', function (event, paragraph, index) {
if ($scope.paragraphUrl) {
if ($scope.paragraphUrl || $scope.revisionView === true) {
return
}
addPara(paragraph, index)
})
$scope.$on('removeParagraph', function (event, paragraphId) {
if ($scope.paragraphUrl) {
if ($scope.paragraphUrl || $scope.revisionView === true) {
return
}
removePara(paragraphId)
})
$scope.$on('moveParagraph', function (event, paragraphId, newIdx) {
if ($scope.revisionView === true) {
return
}
let removedPara = removePara(paragraphId)
if (removedPara && removedPara.length === 1) {
addPara(removedPara[0], newIdx)
@ -958,6 +961,9 @@ function NotebookCtrl ($scope, $route, $routeParams, $location, $rootScope,
})
$scope.$on('insertParagraph', function (event, paragraphId, position) {
if ($scope.revisionView === true) {
return
}
let newIndex = -1
for (let i = 0; i < $scope.note.paragraphs.length; i++) {
if ($scope.note.paragraphs[i].id === paragraphId) {

View file

@ -51,6 +51,10 @@
border-color: #ccc;
}
.revisionTooltip {
z-index: 10003;
}
.caretSeparator {
height: 22px;
line-height: 9px;
@ -313,7 +317,6 @@
max-width: 50%;
}
.inactivelink {
color: darkgrey;
cursor: default;
@ -330,4 +333,3 @@
}
.noteAction.headroom--unpinned { top: -100px; }
.noteAction.headroom--pinned { top: 50px; /** `noteAction` top */ }

View file

@ -610,7 +610,9 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca
let session = editor.getSession()
let dirtyText = session.getValue()
$scope.dirtyText = dirtyText
$scope.startSaveTimer()
if ($scope.dirtyText !== $scope.originalText) {
$scope.startSaveTimer()
}
setParagraphMode(session, dirtyText, editor.getCursorPosition())
}
@ -629,9 +631,18 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca
$scope.editor.getSession().setUseWrapMode(true)
$scope.editor.setTheme('ace/theme/chrome')
$scope.editor.setReadOnly($scope.isRunning($scope.paragraph))
if ($scope.paragraphFocused) {
let prefix = '%' + getInterpreterName($scope.paragraph.text)
let paragraphText = $scope.paragraph.text ? $scope.paragraph.text.trim() : ''
$scope.editor.focus()
$scope.goToEnd($scope.editor)
if (prefix === paragraphText) {
$timeout(function () {
$scope.editor.gotoLine(2, 0)
}, 0)
}
}
autoAdjustEditorHeight(_editor)
@ -839,14 +850,16 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca
let getEditorSetting = function (paragraph, interpreterName) {
let deferred = $q.defer()
websocketMsgSrv.getEditorSetting(paragraph.id, interpreterName)
$timeout(
$scope.$on('editorSetting', function (event, data) {
if (paragraph.id === data.paragraphId) {
deferred.resolve(data)
if (!$scope.revisionView) {
websocketMsgSrv.getEditorSetting(paragraph.id, interpreterName)
$timeout(
$scope.$on('editorSetting', function (event, data) {
if (paragraph.id === data.paragraphId) {
deferred.resolve(data)
}
}
}
), 1000)
}
return deferred.promise
}
@ -1241,23 +1254,28 @@ function ParagraphCtrl ($scope, $rootScope, $route, $window, $routeParams, $loca
}
$scope.updateParagraph = function (oldPara, newPara, updateCallback) {
// 1. get status, refreshed
// 1. can't update on revision view
if ($scope.revisionView === true) {
return
}
// 2. get status, refreshed
const statusChanged = (newPara.status !== oldPara.status)
const resultRefreshed = (newPara.dateFinished !== oldPara.dateFinished) ||
isEmpty(newPara.results) !== isEmpty(oldPara.results) ||
newPara.status === ParagraphStatus.ERROR ||
(newPara.status === ParagraphStatus.FINISHED && statusChanged)
// 2. update texts managed by $scope
// 3. update texts managed by $scope
$scope.updateAllScopeTexts(oldPara, newPara)
// 3. execute callback to update result
// 4. execute callback to update result
updateCallback()
// 4. update remaining paragraph objects
// 5. update remaining paragraph objects
$scope.updateParagraphObjectWhenUpdated(newPara)
// 5. handle scroll down by key properly if new paragraph is added
// 6. handle scroll down by key properly if new paragraph is added
if (statusChanged || resultRefreshed) {
// when last paragraph runs, zeppelin automatically appends new paragraph.
// this broadcast will focus to the newly inserted paragraph

View file

@ -498,6 +498,10 @@ public class ZeppelinConfiguration extends XMLConfiguration {
return getString(ConfVars.ZEPPELIN_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE);
}
public String getJettyName() {
return getString(ConfVars.ZEPPELIN_SERVER_JETTY_NAME);
}
public Map<String, String> dumpConfigurations(ZeppelinConfiguration conf,
ConfigurationKeyPredicate predicate) {
Map<String, String> configurations = new HashMap<>();
@ -646,7 +650,8 @@ public class ZeppelinConfiguration extends XMLConfiguration {
ZEPPELIN_ANONYMOUS_ALLOWED("zeppelin.anonymous.allowed", true),
ZEPPELIN_CREDENTIALS_PERSIST("zeppelin.credentials.persist", true),
ZEPPELIN_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE("zeppelin.websocket.max.text.message.size", "1024000"),
ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED("zeppelin.server.default.dir.allowed", false);
ZEPPELIN_SERVER_DEFAULT_DIR_ALLOWED("zeppelin.server.default.dir.allowed", false),
ZEPPELIN_SERVER_JETTY_NAME("zeppelin.server.jetty.name", null);
private String varName;
@SuppressWarnings("rawtypes")

View file

@ -246,8 +246,13 @@ public class InterpreterSettingManager {
if (!Files.exists(interpreterBindingPath)) {
Files.createFile(interpreterBindingPath);
Set<PosixFilePermission> permissions = EnumSet.of(OWNER_READ, OWNER_WRITE);
Files.setPosixFilePermissions(interpreterBindingPath, permissions);
try {
Set<PosixFilePermission> permissions = EnumSet.of(OWNER_READ, OWNER_WRITE);
Files.setPosixFilePermissions(interpreterBindingPath, permissions);
} catch (UnsupportedOperationException e) {
// File system does not support Posix file permissions (likely windows) - continue anyway.
logger.warn("unable to setPosixFilePermissions on '{}'.", interpreterBindingPath);
};
}
FileOutputStream fos = new FileOutputStream(interpreterBindingPath.toFile(), false);

View file

@ -142,21 +142,13 @@ public class RemoteInterpreter extends Interpreter {
private Map<String, String> getEnvFromInterpreterProperty(Properties property) {
Map<String, String> env = new HashMap<>();
for (Object key : property.keySet()) {
if (isEnvString((String) key)) {
if (RemoteInterpreterUtils.isEnvString((String) key)) {
env.put((String) key, property.getProperty((String) key));
}
}
return env;
}
static boolean isEnvString(String key) {
if (key == null || key.length() == 0) {
return false;
}
return key.matches("^[A-Z_0-9]*");
}
@Override
public String getClassName() {
return className;

View file

@ -353,7 +353,6 @@ public class Note implements Serializable, ParagraphJobListener {
private Paragraph createParagraph(int index, AuthenticationInfo authenticationInfo) {
Paragraph p = new Paragraph(this, this, factory, interpreterSettingManager);
p.setAuthenticationInfo(authenticationInfo);
p.addUser(p, p.getUser());
setParagraphMagic(p, index);
return p;
}

View file

@ -43,6 +43,8 @@ module.exports = {
{ test: /\.eot(\?\S*)?$/, loader: 'url-loader', }, {
test: /\.ttf(\?\S*)?$/, loader: 'url-loader', }, {
test: /\.svg(\?\S*)?$/, loader: 'url-loader', }, {
test: /\.png(\?\S*)?$/, loader: 'url-loader', }, {
test: /\.jpg(\?\S*)?$/, loader: 'url-loader', }, {
test: /\.json$/, loader: 'json-loader' }, ],
}
}

View file

@ -854,13 +854,13 @@ public class RemoteInterpreterTest {
@Test
public void testEnvStringPattern() {
assertFalse(RemoteInterpreter.isEnvString(null));
assertFalse(RemoteInterpreter.isEnvString(""));
assertFalse(RemoteInterpreter.isEnvString("abcDEF"));
assertFalse(RemoteInterpreter.isEnvString("ABC-DEF"));
assertTrue(RemoteInterpreter.isEnvString("ABCDEF"));
assertTrue(RemoteInterpreter.isEnvString("ABC_DEF"));
assertTrue(RemoteInterpreter.isEnvString("ABC_DEF123"));
assertFalse(RemoteInterpreterUtils.isEnvString(null));
assertFalse(RemoteInterpreterUtils.isEnvString(""));
assertFalse(RemoteInterpreterUtils.isEnvString("abcDEF"));
assertFalse(RemoteInterpreterUtils.isEnvString("ABC-DEF"));
assertTrue(RemoteInterpreterUtils.isEnvString("ABCDEF"));
assertTrue(RemoteInterpreterUtils.isEnvString("ABC_DEF"));
assertTrue(RemoteInterpreterUtils.isEnvString("ABC_DEF123"));
}
@Test

View file

@ -217,4 +217,20 @@ public class NoteTest {
assertEquals("getName should return same as getId when name is empty", note.getId(), note.getName());
}
@Test
public void personalizedModeReturnDifferentParagraphInstancePerUser() {
Note note = new Note(repo, interpreterFactory, interpreterSettingManager, jobListenerFactory, index, credentials, noteEventListener);
String user1 = "user1";
String user2 = "user2";
note.setPersonalizedMode(true);
note.addNewParagraph(new AuthenticationInfo(user1));
Paragraph baseParagraph = note.getParagraphs().get(0);
Paragraph user1Paragraph = baseParagraph.getUserParagraph(user1);
Paragraph user2Paragraph = baseParagraph.getUserParagraph(user2);
assertNotEquals(System.identityHashCode(baseParagraph), System.identityHashCode(user1Paragraph));
assertNotEquals(System.identityHashCode(baseParagraph), System.identityHashCode(user2Paragraph));
assertNotEquals(System.identityHashCode(user1Paragraph), System.identityHashCode(user2Paragraph));
}
}