Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bruno Bonnin 2017-01-23 09:05:10 +01:00
commit 2e1bbbd668
42 changed files with 224 additions and 188 deletions

View file

@ -33,7 +33,7 @@ if [[ $# -ne 2 ]]; then
usage
fi
for var in GPG_PASSPHRASE DOCKER_USERNAME; do
for var in GPG_PASSPHRASE; do
if [[ -z "${!var}" ]]; then
echo "You need ${var} variable set"
exit 1
@ -44,18 +44,6 @@ RELEASE_VERSION="$1"
GIT_TAG="$2"
SCALA_VERSION="2.11"
function build_docker_base() {
# build base image
docker build -t ${DOCKER_USERNAME}/zeppelin-base:latest "${BASEDIR}/../scripts/docker/zeppelin-base"
}
function build_docker_image() {
# build release image
echo "FROM ${DOCKER_USERNAME}/zeppelin-base:latest
RUN mkdir /usr/local/zeppelin/
ADD zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME} /usr/local/zeppelin/" > "Dockerfile"
docker build -t ${DOCKER_USERNAME}/zeppelin-release:"${RELEASE_VERSION}" .
}
function make_source_package() {
# create source package
cd ${WORKING_DIR}
@ -112,16 +100,10 @@ function make_binary_release() {
mv "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.md5" "${WORKING_DIR}/"
mv "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.sha512" "${WORKING_DIR}/"
# build docker image if binary_release_name 'all'
if [[ $1 = "all" ]]; then
build_docker_image
fi
# clean up build dir
rm -rf "${WORKING_DIR}/zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}"
}
build_docker_base
git_clone
make_source_package
make_binary_release all "-Pspark-2.1 -Phadoop-2.6 -Pyarn -Ppyspark -Psparkr -Pscala-${SCALA_VERSION}"

View file

@ -30,7 +30,7 @@ if [[ $# -ne 2 ]]; then
usage
fi
for var in GPG_PASSPHRASE ASF_USERID ASF_PASSWORD DOCKER_USERNAME DOCKER_PASSWORD DOCKER_EMAIL; do
for var in GPG_PASSPHRASE ASF_USERID ASF_PASSWORD; do
if [[ -z "${!var}" ]]; then
echo "You need ${var} variable set"
exit 1
@ -67,14 +67,6 @@ function curl_error() {
fi
}
function publish_to_dockerhub() {
# publish images
docker login --username="${DOCKER_USERNAME}" --password="${DOCKER_PASSWORD}" --email="${DOCKER_EMAIL}"
docker push ${DOCKER_USERNAME}/zeppelin-base:latest
docker push ${DOCKER_USERNAME}/zeppelin-release:"${RELEASE_VERSION}"
}
function publish_to_maven() {
cd "${WORKING_DIR}/zeppelin"
@ -102,9 +94,9 @@ function publish_to_maven() {
# build with scala-2.10
echo "mvn clean install -DskipTests \
-Dmaven.repo.local=${tmp_repo} -Pscala-2.10 \
-Dmaven.repo.local=${tmp_repo} -Pscala-2.10 -Pbeam \
${PUBLISH_PROFILES} ${PROJECT_OPTIONS}"
mvn clean install -DskipTests -Dmaven.repo.local="${tmp_repo}" -Pscala-2.10 \
mvn clean install -DskipTests -Dmaven.repo.local="${tmp_repo}" -Pscala-2.10 -Pbeam \
${PUBLISH_PROFILES} ${PROJECT_OPTIONS}
if [[ $? -ne 0 ]]; then
echo "Build with scala 2.10 failed."
@ -161,6 +153,5 @@ function publish_to_maven() {
}
git_clone
publish_to_dockerhub
publish_to_maven
cleanup

View file

@ -253,7 +253,7 @@ The role of registered interpreters, settings and interpreters group are describ
</tr>
<tr>
<td>Success code</td>
<td>201</td>
<td>200</td>
</tr>
<tr>
<td>Fail code</td>
@ -492,7 +492,7 @@ The role of registered interpreters, settings and interpreters group are describ
</tr>
<tr>
<td>Success code</td>
<td>201</td>
<td>200</td>
</tr>
<tr>
<td>Fail code</td>

View file

@ -89,7 +89,7 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete,
</tr>
<tr>
<td>Success code</td>
<td>201</td>
<td>200</td>
</tr>
<tr>
<td> Fail code</td>
@ -318,7 +318,7 @@ Notebooks REST API supports the following operations: List, Create, Get, Delete,
</tr>
<tr>
<td>Success code</td>
<td>201</td>
<td>200</td>
</tr>
<tr>
<td> Fail code</td>

View file

@ -50,8 +50,12 @@ def get(key):
def _on_config_change():
# dpi
dpi = _config['dpi']
matplotlib.rcParams['savefig.dpi'] = dpi
# For older versions of matplotlib, savefig.dpi is not synced with
# figure.dpi by default
matplotlib.rcParams['figure.dpi'] = dpi
if matplotlib.__version__ < '2.0.0':
matplotlib.rcParams['savefig.dpi'] = dpi
# Width and height
width = float(_config['width']) / dpi
@ -75,7 +79,7 @@ def _on_config_change():
def _init_config():
dpi = matplotlib.rcParams['savefig.dpi']
dpi = matplotlib.rcParams['figure.dpi']
fmt = matplotlib.rcParams['savefig.format']
width, height = matplotlib.rcParams['figure.figsize']
fontsize = matplotlib.rcParams['font.size']

View file

@ -39,7 +39,6 @@
<hadoop.common.version>2.7.2</hadoop.common.version>
<h2.version>1.4.190</h2.version>
<commons.dbcp2.version>2.0.1</commons.dbcp2.version>
<hadoop-common.version>2.6.0</hadoop-common.version>
<!--test library versions-->
<mockrunner.jdbc.version>1.0.8</mockrunner.jdbc.version>
@ -80,13 +79,6 @@
<version>${jline.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.common.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
@ -122,7 +114,8 @@
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop-common.version}</version>
<version>${hadoop.common.version}</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>com.sun.jersey</groupId>

View file

@ -20,7 +20,7 @@ package org.apache.zeppelin.livy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.annotations.SerializedName;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.zeppelin.interpreter.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

View file

@ -17,7 +17,7 @@
package org.apache.zeppelin.livy;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;

View file

@ -33,6 +33,7 @@
<name>Zeppelin: Markdown interpreter</name>
<properties>
<commons.lang3.version>3.4</commons.lang3.version>
<markdown4j.version>2.2-cj-1.0</markdown4j.version>
<pegdown.version>1.6.0</pegdown.version>
</properties>
@ -67,6 +68,12 @@
<version>${pegdown.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -27,7 +27,7 @@ import org.pegdown.plugins.PegDownPlugins;
public class PegdownParser implements MarkdownParser {
private PegDownProcessor processor;
public static final long PARSING_TIMEOUT_AS_MILLIS = 5000;
public static final long PARSING_TIMEOUT_AS_MILLIS = 10000;
public static final int OPTIONS = Extensions.ALL_WITH_OPTIONALS - Extensions.ANCHORLINKS;
public PegdownParser() {

View file

@ -20,7 +20,6 @@ package org.apache.zeppelin.markdown;
import static org.junit.Assert.assertEquals;
import java.util.Properties;
import org.apache.zeppelin.interpreter.InterpreterResult;
import static org.apache.zeppelin.markdown.PegdownParser.wrapWithMarkdownClassDiv;
@ -31,9 +30,11 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PegdownParserTest {
Logger logger = LoggerFactory.getLogger(PegdownParserTest.class);
Markdown md;
@Before
@ -317,7 +318,19 @@ public class PegdownParserTest {
.toString();
InterpreterResult result = md.interpret(input, null);
assertThat(result.message().get(0).getData(), CoreMatchers.containsString("<img src=\"http://www.websequencediagrams.com/?png="));
// assert statement below can fail depends on response of websequence service.
// To make unittest independent from websequence service,
// catch exception, log and pass instead of assert.
//
//assertThat(result.message().get(0).getData(), CoreMatchers.containsString("<img src=\"http://www.websequencediagrams.com/?png="));
System.err.println(result.message().get(0).getData());
if (!result.message().get(0).getData().contains(
"<img src=\"http://www.websequencediagrams.com/?png=")) {
logger.error("Expected {} but found {}",
"<img src=\"http://www.websequencediagrams.com/?png=", result.message().get(0).getData());
}
}
@Test

View file

@ -2,8 +2,8 @@
"paragraphs": [
{
"text": "%md\n\n\n### [Apache Pig](http://pig.apache.org/) is a platform for analyzing large data sets that consists of a high-level language for expressing data analysis programs, coupled with infrastructure for evaluating these programs. The salient property of Pig programs is that their structure is amenable to substantial parallelization, which in turns enables them to handle very large data sets.\n\nPig\u0027s language layer currently consists of a textual language called Pig Latin, which has the following key properties:\n\n* Ease of programming. It is trivial to achieve parallel execution of simple, \"embarrassingly parallel\" data analysis tasks. Complex tasks comprised of multiple interrelated data transformations are explicitly encoded as data flow sequences, making them easy to write, understand, and maintain.\n* Optimization opportunities. The way in which tasks are encoded permits the system to optimize their execution automatically, allowing the user to focus on semantics rather than efficiency.\n* Extensibility. Users can create their own functions to do special-purpose processing.\n",
"user": "user1",
"dateUpdated": "Jan 6, 2017 3:55:03 PM",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:48:50 PM",
"config": {
"colWidth": 12.0,
"enabled": true,
@ -33,15 +33,15 @@
"jobName": "paragraph_1483277502513_1156234051",
"id": "20170101-213142_1565013608",
"dateCreated": "Jan 1, 2017 9:31:42 PM",
"dateStarted": "Jan 6, 2017 3:55:03 PM",
"dateFinished": "Jan 6, 2017 3:55:04 PM",
"dateStarted": "Jan 22, 2017 12:48:50 PM",
"dateFinished": "Jan 22, 2017 12:48:51 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
{
"text": "%md\n\nThis pig tutorial use pig to do the same thing as spark tutorial. The default mode is mapreduce, you can also use other modes like local/tez_local/tez. For mapreduce mode, you need to have hadoop installed and export `HADOOP_CONF_DIR` in `zeppelin-env.sh`\n\nThe tutorial consists of 3 steps.\n\n* Use shell interpreter to download bank.csv and upload it to hdfs\n* use `%pig` to process the data\n* use `%pig.query` to query the data",
"user": "user1",
"dateUpdated": "Jan 6, 2017 3:55:18 PM",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:48:55 PM",
"config": {
"colWidth": 12.0,
"enabled": true,
@ -71,15 +71,51 @@
"jobName": "paragraph_1483689316217_-629483391",
"id": "20170106-155516_1050601059",
"dateCreated": "Jan 6, 2017 3:55:16 PM",
"dateStarted": "Jan 6, 2017 3:55:18 PM",
"dateFinished": "Jan 6, 2017 3:55:18 PM",
"dateStarted": "Jan 22, 2017 12:48:55 PM",
"dateFinished": "Jan 22, 2017 12:48:55 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
{
"text": "%sh\n\nwget https://s3.amazonaws.com/apache-zeppelin/tutorial/bank/bank.csv\nhadoop fs -put bank.csv .\n",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:51:48 PM",
"config": {
"colWidth": 12.0,
"enabled": true,
"results": {},
"editorSetting": {
"language": "text",
"editOnDblClick": false
},
"editorMode": "ace/mode/text"
},
"settings": {
"params": {},
"forms": {}
},
"results": {
"code": "SUCCESS",
"msg": [
{
"type": "TEXT",
"data": "--2017-01-22 12:51:48-- https://s3.amazonaws.com/apache-zeppelin/tutorial/bank/bank.csv\nResolving s3.amazonaws.com... 52.216.80.227\nConnecting to s3.amazonaws.com|52.216.80.227|:443... connected.\nHTTP request sent, awaiting response... 200 OK\nLength: 461474 (451K) [application/octet-stream]\nSaving to: \u0027bank.csv.3\u0027\n\n 0K .......... .......... .......... .......... .......... 11% 141K 3s\n 50K .......... .......... .......... .......... .......... 22% 243K 2s\n 100K .......... .......... .......... .......... .......... 33% 449K 1s\n 150K .......... .......... .......... .......... .......... 44% 413K 1s\n 200K .......... .......... .......... .......... .......... 55% 746K 1s\n 250K .......... .......... .......... .......... .......... 66% 588K 0s\n 300K .......... .......... .......... .......... .......... 77% 840K 0s\n 350K .......... .......... .......... .......... .......... 88% 795K 0s\n 400K .......... .......... .......... .......... .......... 99% 1.35M 0s\n 450K 100% 13.2K\u003d1.1s\n\n2017-01-22 12:51:50 (409 KB/s) - \u0027bank.csv.3\u0027 saved [461474/461474]\n\n17/01/22 12:51:51 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable\n"
}
]
},
"apps": [],
"jobName": "paragraph_1485058437578_-1906301827",
"id": "20170122-121357_640055590",
"dateCreated": "Jan 22, 2017 12:13:57 PM",
"dateStarted": "Jan 22, 2017 12:51:48 PM",
"dateFinished": "Jan 22, 2017 12:51:52 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
{
"text": "%pig\n\nbankText \u003d load \u0027bank.csv\u0027 using PigStorage(\u0027;\u0027);\nbank \u003d foreach bankText generate $0 as age, $1 as job, $2 as marital, $3 as education, $5 as balance; \nbank \u003d filter bank by age !\u003d \u0027\"age\"\u0027;\nbank \u003d foreach bank generate (int)age, REPLACE(job,\u0027\"\u0027,\u0027\u0027) as job, REPLACE(marital, \u0027\"\u0027, \u0027\u0027) as marital, (int)(REPLACE(balance, \u0027\"\u0027, \u0027\u0027)) as balance;\n\n-- The following statement is optional, it depends on whether your needs.\n-- store bank into \u0027clean_bank.csv\u0027 using PigStorage(\u0027;\u0027);\n\n\n",
"user": "user1",
"dateUpdated": "Jan 6, 2017 3:57:11 PM",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:49:11 PM",
"config": {
"colWidth": 12.0,
"editorMode": "ace/mode/pig",
@ -102,15 +138,15 @@
"jobName": "paragraph_1483277250237_-466604517",
"id": "20161228-140640_1560978333",
"dateCreated": "Jan 1, 2017 9:27:30 PM",
"dateStarted": "Jan 6, 2017 3:57:11 PM",
"dateFinished": "Jan 6, 2017 3:57:13 PM",
"dateStarted": "Jan 22, 2017 12:49:11 PM",
"dateFinished": "Jan 22, 2017 12:49:13 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
{
"text": "%pig.query\n\nbank_data \u003d filter bank by age \u003c 30;\nb \u003d group bank_data by age;\nforeach b generate group, COUNT($1);\n\n",
"user": "user1",
"dateUpdated": "Jan 6, 2017 3:57:15 PM",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:49:16 PM",
"config": {
"colWidth": 4.0,
"editorMode": "ace/mode/pig",
@ -139,7 +175,7 @@
"msg": [
{
"type": "TABLE",
"data": "group\tnull\n19\t4\n20\t3\n21\t7\n22\t9\n23\t20\n24\t24\n25\t44\n26\t77\n27\t94\n28\t103\n29\t97\n"
"data": "group\tcol_1\n19\t4\n20\t3\n21\t7\n22\t9\n23\t20\n24\t24\n25\t44\n26\t77\n27\t94\n28\t103\n29\t97\n"
}
]
},
@ -147,15 +183,15 @@
"jobName": "paragraph_1483277250238_-465450270",
"id": "20161228-140730_1903342877",
"dateCreated": "Jan 1, 2017 9:27:30 PM",
"dateStarted": "Jan 6, 2017 3:57:15 PM",
"dateFinished": "Jan 6, 2017 3:57:16 PM",
"dateStarted": "Jan 22, 2017 12:49:16 PM",
"dateFinished": "Jan 22, 2017 12:49:30 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
{
"text": "%pig.query\n\nbank_data \u003d filter bank by age \u003c ${maxAge\u003d40};\nb \u003d group bank_data by age;\nforeach b generate group, COUNT($1);",
"user": "user1",
"dateUpdated": "Jan 6, 2017 3:57:18 PM",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:49:18 PM",
"config": {
"colWidth": 4.0,
"editorMode": "ace/mode/pig",
@ -192,7 +228,7 @@
"msg": [
{
"type": "TABLE",
"data": "group\tnull\n19\t4\n20\t3\n21\t7\n22\t9\n23\t20\n24\t24\n25\t44\n26\t77\n27\t94\n28\t103\n29\t97\n30\t150\n31\t199\n32\t224\n33\t186\n34\t231\n35\t180\n"
"data": "group\tcol_1\n19\t4\n20\t3\n21\t7\n22\t9\n23\t20\n24\t24\n25\t44\n26\t77\n27\t94\n28\t103\n29\t97\n30\t150\n31\t199\n32\t224\n33\t186\n34\t231\n35\t180\n"
}
]
},
@ -200,15 +236,15 @@
"jobName": "paragraph_1483277250239_-465835019",
"id": "20161228-154918_1551591203",
"dateCreated": "Jan 1, 2017 9:27:30 PM",
"dateStarted": "Jan 6, 2017 3:57:18 PM",
"dateFinished": "Jan 6, 2017 3:57:19 PM",
"dateStarted": "Jan 22, 2017 12:49:18 PM",
"dateFinished": "Jan 22, 2017 12:49:32 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
{
"text": "%pig.query\n\nbank_data \u003d filter bank by marital\u003d\u003d\u0027${marital\u003dsingle,single|divorced|married}\u0027;\nb \u003d group bank_data by age;\nforeach b generate group, COUNT($1) as c;\n\n\n",
"user": "user1",
"dateUpdated": "Jan 6, 2017 3:57:24 PM",
"user": "anonymous",
"dateUpdated": "Jan 22, 2017 12:49:20 PM",
"config": {
"colWidth": 4.0,
"editorMode": "ace/mode/pig",
@ -264,8 +300,8 @@
"jobName": "paragraph_1483277250240_-480070728",
"id": "20161228-142259_575675591",
"dateCreated": "Jan 1, 2017 9:27:30 PM",
"dateStarted": "Jan 6, 2017 3:57:20 PM",
"dateFinished": "Jan 6, 2017 3:57:20 PM",
"dateStarted": "Jan 22, 2017 12:49:30 PM",
"dateFinished": "Jan 22, 2017 12:49:34 PM",
"status": "FINISHED",
"progressUpdateIntervalMs": 500
},
@ -289,28 +325,10 @@
"name": "Zeppelin Tutorial/Using Pig for querying data",
"id": "2C57UKYWR",
"angularObjects": {
"2C3DR183X:shared_process": [],
"2C5VH924X:shared_process": [],
"2C686X8ZH:shared_process": [],
"2C66Z9XPQ:shared_process": [],
"2C3JKFMJU:shared_process": [],
"2C69WE69N:shared_process": [],
"2C3RWCVAG:shared_process": [],
"2C4HKDCQW:shared_process": [],
"2C4BJDRRZ:shared_process": [],
"2C6V3D44K:shared_process": [],
"2C3VECEG2:shared_process": [],
"2C5SRRXHM:shared_process": [],
"2C5DCRVGM:shared_process": [],
"2C66GE1VB:shared_process": [],
"2C3PTPMUH:shared_process": [],
"2C48Y7FSJ:shared_process": [],
"2C4ZD49PF:shared_process": [],
"2C63XW4XE:shared_process": [],
"2C4UB1UZA:shared_process": [],
"2C5S1R21W:shared_process": [],
"2C3SQSB7V:shared_process": []
"2C9KGCHDE:shared_process": [],
"2C8X2BS16:shared_process": []
},
"config": {},
"info": {}
}
}

View file

@ -17,7 +17,7 @@
package org.apache.zeppelin.pig;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.pig.PigServer;
import org.apache.pig.backend.BackendException;

View file

@ -18,8 +18,8 @@
package org.apache.zeppelin.pig;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.pig.PigServer;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.tools.pigstats.*;

View file

@ -19,8 +19,8 @@
package org.apache.zeppelin.pig;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.pig.PigServer;
import org.apache.pig.data.Tuple;
import org.apache.pig.impl.logicalLayer.FrontendException;
@ -114,7 +114,7 @@ public class PigQueryInterpreter extends BasePigInterpreter {
resultBuilder.append("\n");
firstRow = false;
}
resultBuilder.append(StringUtils.join(tuple, "\t"));
resultBuilder.append(StringUtils.join(tuple.iterator(), "\t"));
resultBuilder.append("\n");
}
if (index >= maxResult && iter.hasNext()) {

View file

@ -19,8 +19,8 @@ package org.apache.zeppelin.pig;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.pig.PigRunner;
import org.apache.pig.backend.hadoop.executionengine.tez.TezExecType;
import org.apache.pig.tools.pigstats.InputStats;

View file

@ -34,6 +34,7 @@
<properties>
<!--library versions -->
<commons.lang3.version>3.4</commons.lang3.version>
<commons.exec.version>1.3</commons.exec.version>
</properties>
@ -61,6 +62,12 @@
<version>${commons.exec.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>

View file

@ -44,5 +44,5 @@ if [[ -n "$PYTHON" ]] ; then
conda update -q conda
conda info -a
conda config --add channels conda-forge
conda install -q matplotlib=1.5.3 pandasql
conda install -q matplotlib pandasql
fi

View file

@ -23,6 +23,7 @@ import org.apache.zeppelin.display.{AngularObject, AngularObjectRegistry, GUI}
import org.apache.zeppelin.interpreter._
import org.apache.zeppelin.user.AuthenticationInfo
import org.scalatest.concurrent.Eventually
import org.scalatest.time.{Seconds, Span}
import org.scalatest.{BeforeAndAfter, BeforeAndAfterEach, FlatSpec, Matchers}
/**
@ -61,12 +62,12 @@ trait AbstractAngularElemTest
// click create thread for callback function to run. So it'll may not immediately invoked
// after click. therefore eventually should be
click(elem)
eventually {
eventually (timeout(Span(5, Seconds))) {
a should be(1)
}
click(elem)
eventually {
eventually (timeout(Span(5, Seconds))) {
a should be(2)
}
@ -120,7 +121,7 @@ trait AbstractAngularElemTest
click(elem)
eventually { modelValue should be("value")}
eventually (timeout(Span(5, Seconds))) { modelValue should be("value")}
}

View file

@ -37,7 +37,6 @@
<properties>
<!--library versions-->
<commons.lang3.version>3.4</commons.lang3.version>
<commons.pool2.version>2.3</commons.pool2.version>
<commons.exec.version>1.3</commons.exec.version>
<maven.plugin.api.version>3.0</maven.plugin.api.version>
@ -88,12 +87,6 @@
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
<!-- Aether :: maven dependency resolution -->
<dependency>
<groupId>org.apache.maven</groupId>

View file

@ -17,7 +17,7 @@
package org.apache.zeppelin.dep;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang.Validate;
import org.apache.maven.repository.internal.MavenRepositorySystemSession;
import org.sonatype.aether.RepositorySystem;
import org.sonatype.aether.RepositorySystemSession;

View file

@ -16,7 +16,7 @@
*/
package org.apache.zeppelin.dep;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang.StringUtils.isNotBlank;
import org.sonatype.aether.repository.Authentication;
import org.sonatype.aether.repository.Proxy;

View file

@ -52,7 +52,7 @@ import java.util.concurrent.TimeUnit;
*/
public class RemoteInterpreterEventPoller extends Thread {
private static final Logger logger = LoggerFactory.getLogger(RemoteInterpreterEventPoller.class);
private static final ScheduledExecutorService appendService =
private final ScheduledExecutorService appendService =
Executors.newSingleThreadScheduledExecutor();
private final RemoteInterpreterProcessListener listener;
private final ApplicationEventListener appListener;

View file

@ -380,6 +380,10 @@
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</exclusion>
</exclusions>
</dependency>

View file

@ -144,9 +144,6 @@ public class HeliumRestApi {
} catch (IOException e) {
logger.error(e.getMessage(), e);
return new JsonResponse(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()).build();
} catch (TaskRunnerException e) {
logger.error(e.getMessage(), e);
return new JsonResponse(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()).build();
}
}
@ -159,9 +156,6 @@ public class HeliumRestApi {
} catch (IOException e) {
logger.error(e.getMessage(), e);
return new JsonResponse(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()).build();
} catch (TaskRunnerException e) {
logger.error(e.getMessage(), e);
return new JsonResponse(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()).build();
}
}
@ -180,7 +174,7 @@ public class HeliumRestApi {
try {
helium.setVisualizationPackageOrder(orderedList);
} catch (IOException | TaskRunnerException e) {
} catch (IOException e) {
logger.error(e.getMessage(), e);
return new JsonResponse(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()).build();
}

View file

@ -123,7 +123,7 @@ public class InterpreterRestApi {
.createNewSetting(request.getName(), request.getGroup(), request.getDependencies(),
request.getOption(), p);
logger.info("new setting created with {}", interpreterSetting.getId());
return new JsonResponse<>(Status.CREATED, "", interpreterSetting).build();
return new JsonResponse<>(Status.OK, "", interpreterSetting).build();
} catch (InterpreterException | IOException e) {
logger.error("Exception in InterpreterRestApi while creating ", e);
return new JsonResponse<>(Status.NOT_FOUND, e.getMessage(), ExceptionUtils.getStackTrace(e))
@ -237,7 +237,7 @@ public class InterpreterRestApi {
return new JsonResponse<>(Status.INTERNAL_SERVER_ERROR, e.getMessage(),
ExceptionUtils.getStackTrace(e)).build();
}
return new JsonResponse(Status.CREATED).build();
return new JsonResponse(Status.OK).build();
}
/**

View file

@ -323,7 +323,7 @@ public class NotebookRestApi {
public Response importNote(String req) throws IOException {
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
Note newNote = notebook.importNote(req, null, subject);
return new JsonResponse<>(Status.CREATED, "", newNote.getId()).build();
return new JsonResponse<>(Status.OK, "", newNote.getId()).build();
}
/**
@ -359,7 +359,7 @@ public class NotebookRestApi {
note.persist(subject);
notebookServer.broadcastNote(note);
notebookServer.broadcastNoteList(subject, SecurityUtils.getRoles());
return new JsonResponse<>(Status.CREATED, "", note.getId()).build();
return new JsonResponse<>(Status.OK, "", note.getId()).build();
}
/**
@ -391,7 +391,7 @@ public class NotebookRestApi {
* Clone note REST API
*
* @param noteId ID of Note
* @return JSON with status.CREATED
* @return JSON with status.OK
* @throws IOException, CloneNotSupportedException, IllegalArgumentException
*/
@POST
@ -410,7 +410,7 @@ public class NotebookRestApi {
Note newNote = notebook.cloneNote(noteId, newNoteName, subject);
notebookServer.broadcastNote(newNote);
notebookServer.broadcastNoteList(subject, SecurityUtils.getRoles());
return new JsonResponse<>(Status.CREATED, "", newNote.getId()).build();
return new JsonResponse<>(Status.OK, "", newNote.getId()).build();
}
/**
@ -445,7 +445,7 @@ public class NotebookRestApi {
note.persist(subject);
notebookServer.broadcastNote(note);
return new JsonResponse<>(Status.CREATED, "", p.getId()).build();
return new JsonResponse<>(Status.OK, "", p.getId()).build();
}
/**

View file

@ -121,7 +121,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
InterpreterSetting created = convertResponseToInterpreterSetting(postResponse);
String newSettingId = created.getId();
// then : call create setting API
assertThat("test create method:", post, isCreated());
assertThat("test create method:", post, isAllowed());
post.releaseConnection();
// when: call read setting API
@ -168,7 +168,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
" }]," +
"\"option\": { \"remote\": true, \"session\": false }}";
PostMethod post = httpPost("/interpreter/setting", reqBody1);
assertThat("test create method:", post, isCreated());
assertThat("test create method:", post, isAllowed());
post.releaseConnection();
String reqBody2 = "{\"name\":\"" + md2Name + "\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"}," +
@ -179,7 +179,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
" }]," +
"\"option\": { \"remote\": true, \"session\": false }}";
post = httpPost("/interpreter/setting", reqBody2);
assertThat("test create method:", post, isCreated());
assertThat("test create method:", post, isAllowed());
post.releaseConnection();
// 1. Call settings API
@ -349,7 +349,7 @@ public class InterpreterRestApiTest extends AbstractTestRestApi {
"\",\"url\":\"https://repo1.maven.org/maven2\",\"snapshot\":\"false\"}";
PostMethod post = httpPost("/interpreter/repository/", jsonRequest);
assertThat("Test create method:", post, isCreated());
assertThat("Test create method:", post, isAllowed());
post.releaseConnection();
// Call delete repository API

View file

@ -126,7 +126,7 @@ public class NotebookRestApiTest extends AbstractTestRestApi {
Note note1 = ZeppelinServer.notebook.createNote(anonymous);
PostMethod post = httpPost("/notebook/" + note1.getId(), "");
LOG.info("testCloneNote response\n" + post.getResponseBodyAsString());
assertThat(post, isCreated());
assertThat(post, isAllowed());
Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
}.getType());
String clonedNoteId = (String) resp.get("body");

View file

@ -152,7 +152,7 @@ public class NotebookSecurityRestApiTest extends AbstractTestRestApi {
private String createNoteForUser(String noteName, String user, String pwd) throws IOException {
String jsonRequest = "{\"name\":\"" + noteName + "\"}";
PostMethod post = httpPost("/notebook/", jsonRequest, user, pwd);
assertThat("test note create method:", post, isCreated());
assertThat("test note create method:", post, isAllowed());
Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
}.getType());
post.releaseConnection();

View file

@ -137,7 +137,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
"]}";
PostMethod post = httpPost("/notebook/", jsonRequest);
LOG.info("testNoteCreate \n" + post.getResponseBodyAsString());
assertThat("test note create method:", post, isCreated());
assertThat("test note create method:", post, isAllowed());
Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
}.getType());
@ -172,7 +172,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
String jsonRequest = "{\"name\":\"" + noteName + "\"}";
PostMethod post = httpPost("/notebook/", jsonRequest);
LOG.info("testNoteCreate \n" + post.getResponseBodyAsString());
assertThat("test note create method:", post, isCreated());
assertThat("test note create method:", post, isAllowed());
Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
}.getType());
@ -262,7 +262,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
String oldJson = getNoteContent(sourceNoteId);
// call note post
PostMethod importPost = httpPost("/notebook/import/", oldJson);
assertThat(importPost, isCreated());
assertThat(importPost, isAllowed());
resp =
gson.fromJson(importPost.getResponseBodyAsString(),
new TypeToken<Map<String, Object>>() {}.getType());
@ -326,7 +326,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
String jsonRequest = "{\"name\":\"" + noteName + "\"}";
PostMethod post = httpPost("/notebook/" + sourceNoteId, jsonRequest);
LOG.info("testNoteClone \n" + post.getResponseBodyAsString());
assertThat("test note clone method:", post, isCreated());
assertThat("test note clone method:", post, isAllowed());
Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
}.getType());
@ -590,7 +590,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
String jsonRequest = "{\"title\": \"title1\", \"text\": \"text1\"}";
PostMethod post = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest);
LOG.info("testInsertParagraph response\n" + post.getResponseBodyAsString());
assertThat("Test insert method:", post, isCreated());
assertThat("Test insert method:", post, isAllowed());
post.releaseConnection();
Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {
@ -613,7 +613,7 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
String jsonRequest2 = "{\"index\": 0, \"title\": \"title2\", \"text\": \"text2\"}";
PostMethod post2 = httpPost("/notebook/" + note.getId() + "/paragraph", jsonRequest2);
LOG.info("testInsertParagraph response2\n" + post2.getResponseBodyAsString());
assertThat("Test insert method:", post2, isCreated());
assertThat("Test insert method:", post2, isAllowed());
post2.releaseConnection();
Paragraph paragraphAtIdx0 = note.getParagraphs().get(0);

View file

@ -41,7 +41,7 @@ class AbstractFunctionalSuite extends FunSuite with WebBrowser with BeforeAndAft
override def beforeAll() = {
"../bin/zeppelin-daemon.sh start" !
eventually (timeout(Span(20, Seconds))) {
eventually (timeout(Span(180, Seconds))) {
go to SERVER_ADDRESS
assert(find("welcome").isDefined)
}

View file

@ -28,7 +28,7 @@ import AbstractFunctionalSuite.SERVER_ADDRESS
class WelcomePageSuite(implicit driver: WebDriver) extends FunSuite with WebBrowser {
test("Welcome sign is correct") {
eventually (timeout(Span(20, Seconds))) {
eventually (timeout(Span(180, Seconds))) {
go to SERVER_ADDRESS
assert(find("welcome").isDefined)
}

View file

@ -98,10 +98,19 @@ function JobmanagerCtrl($scope, websocketMsgSrv, $interval, ngToast, $q, $timeou
filterValueInterpreter: '*',
isSortByAsc: true
};
$scope.sortTooltipMsg = 'Switch to sort by desc';
$scope.jobTypeFilter = jobManagerFilter;
websocketMsgSrv.getNoteJobsList();
$scope.$watch('filterConfig.isSortByAsc', function (value) {
if (value) {
$scope.sortTooltipMsg = 'Switch to sort by desc';
} else {
$scope.sortTooltipMsg = 'Switch to sort by asc';
}
});
$scope.$on('$destroy', function() {
websocketMsgSrv.unsubscribeJobManager();
});

View file

@ -18,6 +18,7 @@ function jobManagerFilter() {
function filterContext(jobItems, filterConfig) {
var filterValueInterpreter = filterConfig.filterValueInterpreter;
var filterValueNotebookName = filterConfig.filterValueNotebookName;
var isSortByAsc = filterConfig.isSortByAsc;
var filterItems = jobItems;
if (filterValueInterpreter === undefined) {
@ -36,7 +37,11 @@ function jobManagerFilter() {
});
}
return filterItems;
filterItems = _.sortBy(filterItems, function(sortItem) {
return sortItem.noteName.toLowerCase();
});
return isSortByAsc ? filterItems : filterItems.reverse();
}
return filterContext;
}

View file

@ -34,7 +34,16 @@ limitations under the License.
<div class="row">
<div class="col-md-6 text-left">
<div class="form-inline">
<span class="labelBtn btn-group" style="margin-left: 0px; padding-left: 10px;">
<span class="labelBtn btn-group">
<button type="button"
class="btn btn-default"
style="width: 25px; height: 25px; margin-right: 0px; padding: 1px 0px 3px 3px"
ng-click="onChangeSortAsc()"
tooltip-placement="right" tooltip="{{sortTooltipMsg}}">
<i class="fa" ng-class="{true: 'fa-sort-amount-asc', false : 'fa-sort-amount-desc'}[filterConfig.isSortByAsc]"></i>
</button>
</span>
<span class="labelBtn btn-group" style="margin-left: 0px; padding-left: 3px;">
<button type="button" class="btn btn-default btn-xs dropdown-toggle"
data-toggle="dropdown"
style="min-width: 100px; text-align: right !important;">
@ -136,7 +145,7 @@ limitations under the License.
</div>
<div
ng-if="JobInfomationsByFilter.length > 0"
ng-repeat="notebookJob in JobInfomationsByFilter"
ng-repeat="notebookJob in JobInfomationsByFilter track by $index"
class="paragraph-col">
<div ng-include src="'app/jobmanager/jobs/job.html'"
class="job-space box job-margin"

View file

@ -1040,7 +1040,9 @@ function ParagraphCtrl($scope, $rootScope, $route, $window, $routeParams, $locat
$scope.paragraph.title = data.paragraph.title;
$scope.paragraph.lineNumbers = data.paragraph.lineNumbers;
$scope.paragraph.status = data.paragraph.status;
$scope.paragraph.results = data.paragraph.results;
if (data.paragraph.status !== 'RUNNING') {
$scope.paragraph.results = data.paragraph.results;
}
$scope.paragraph.settings = data.paragraph.settings;
if ($scope.editor) {
$scope.editor.setReadOnly($scope.isRunning(data.paragraph));

View file

@ -36,6 +36,7 @@
<properties>
<!--library versions-->
<commons.lang3.version>3.4</commons.lang3.version>
<commons.vfs2.version>2.0</commons.vfs2.version>
<aws.sdk.s3.version>1.10.62</aws.sdk.s3.version>
<azure.storage.version>4.0.0</azure.storage.version>
@ -277,6 +278,12 @@
<version>${jetty.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons.lang3.version}</version>
</dependency>
</dependencies>
<build>

View file

@ -16,7 +16,6 @@
*/
package org.apache.zeppelin.helium;
import com.github.eirslett.maven.plugins.frontend.lib.TaskRunnerException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.commons.io.FileUtils;
@ -31,8 +30,6 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.*;
/**
@ -54,7 +51,7 @@ public class Helium {
String defaultLocalRegistryPath,
HeliumVisualizationFactory visualizationFactory,
HeliumApplicationFactory applicationFactory)
throws IOException, TaskRunnerException {
throws IOException {
this.heliumConfPath = heliumConfPath;
this.defaultLocalRegistryPath = defaultLocalRegistryPath;
this.visualizationFactory = visualizationFactory;
@ -206,11 +203,11 @@ public class Helium {
return null;
}
public File recreateVisualizationBundle() throws IOException, TaskRunnerException {
public File recreateVisualizationBundle() throws IOException {
return visualizationFactory.bundle(getVisualizationPackagesToBundle(), true);
}
public void enable(String name, String artifact) throws IOException, TaskRunnerException {
public void enable(String name, String artifact) throws IOException {
HeliumPackageSearchResult pkgInfo = getPackageInfo(name, artifact);
// no package found.
@ -229,7 +226,7 @@ public class Helium {
save();
}
public void disable(String name) throws IOException, TaskRunnerException {
public void disable(String name) throws IOException {
String artifact = heliumConf.getEnabledPackages().get(name);
if (artifact == null) {
@ -344,7 +341,7 @@ public class Helium {
}
public void setVisualizationPackageOrder(List<String> orderedPackageList)
throws IOException, TaskRunnerException {
throws IOException {
heliumConf.setVisualizationDisplayOrder(orderedPackageList);
// if package is visualization, rebuild bundle

View file

@ -94,12 +94,12 @@ public class HeliumVisualizationFactory {
return new ProxyConfig(proxy);
}
public File bundle(List<HeliumPackage> pkgs) throws IOException, TaskRunnerException {
public File bundle(List<HeliumPackage> pkgs) throws IOException {
return bundle(pkgs, false);
}
public synchronized File bundle(List<HeliumPackage> pkgs, boolean forceRefresh)
throws IOException, TaskRunnerException {
throws IOException {
// package.json
URL pkgUrl = Resources.getResource("helium/package.json");
String pkgJson = Resources.toString(pkgUrl, Charsets.UTF_8);
@ -213,8 +213,12 @@ public class HeliumVisualizationFactory {
}
out.reset();
npmCommand("install");
npmCommand("run bundle");
try {
npmCommand("install");
npmCommand("run bundle");
} catch (TaskRunnerException e) {
throw new IOException(new String(out.toByteArray()));
}
File visBundleJs = new File(workingDirectory, "vis.bundle.js");
if (!visBundleJs.isFile()) {

View file

@ -21,8 +21,7 @@ module.exports = {
filename: 'vis.bundle.js',
},
resolve: {
root: __dirname + "/node_modules",
extensions: [".js"]
root: __dirname + "/node_modules"
},
module: {
loaders: [{

View file

@ -736,35 +736,32 @@ public class NotebookTest implements JobListenerFactory{
Note note = notebook.createNote(anonymous);
factory.setInterpreters(anonymous.getUser(), note.getId(), factory.getDefaultInterpreterSettingList());
ArrayList<Paragraph> paragraphs = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Paragraph tmp = note.addParagraph(AuthenticationInfo.ANONYMOUS);
tmp.setText("p" + tmp.getId());
paragraphs.add(tmp);
}
// create three paragraphs
Paragraph p1 = note.addParagraph(anonymous);
p1.setText("sleep 1000");
Paragraph p2 = note.addParagraph(anonymous);
p2.setText("sleep 1000");
Paragraph p3 = note.addParagraph(anonymous);
p3.setText("sleep 1000");
for (Paragraph p : paragraphs) {
assertEquals(Job.Status.READY, p.getStatus());
}
note.runAll();
while (paragraphs.get(0).getStatus() != Status.FINISHED) Thread.yield();
// wait until first paragraph finishes and second paragraph starts
while (p1.getStatus() != Status.FINISHED || p2.getStatus() != Status.RUNNING) Thread.yield();
assertEquals(Status.FINISHED, p1.getStatus());
assertEquals(Status.RUNNING, p2.getStatus());
assertEquals(Status.PENDING, p3.getStatus());
// restart interpreter
factory.restart(factory.getInterpreterSettings(note.getId()).get(0).getId());
boolean isAborted = false;
for (Paragraph p : paragraphs) {
logger.debug(p.getStatus().name());
if (isAborted) {
assertEquals(Job.Status.ABORT, p.getStatus());
}
if (p.getStatus() == Status.ABORT) {
isAborted = true;
}
}
// make sure three differnt status aborted well.
assertEquals(Status.FINISHED, p1.getStatus());
assertEquals(Status.ABORT, p2.getStatus());
assertEquals(Status.ABORT, p3.getStatus());
assertTrue(isAborted);
notebook.removeNote(note.getId(), anonymous);
}