Merge pull request #4 from apache/master

merge master
This commit is contained in:
mfelgamal 2016-07-19 21:28:46 +03:00 committed by GitHub
commit 03a1e80f8f
536 changed files with 26976 additions and 12236 deletions

View file

@ -1,6 +1,6 @@
### What is this PR for?
A few sentences describing the overall goals of the pull request's commits.
First time? Check out the contributing guide - https://github.com/apache/incubator-zeppelin/blob/master/CONTRIBUTING.md
First time? Check out the contributing guide - https://github.com/apache/zeppelin/blob/master/CONTRIBUTING.md
### What type of PR is it?

13
.gitignore vendored
View file

@ -26,27 +26,32 @@ conf/truststore
conf/interpreter.json
conf/notebook-authorization.json
conf/shiro.ini
conf/credentials.json
# other generated files
spark/dependency-reduced-pom.xml
reports
#webapp
# webapp
zeppelin-web/node_modules
zeppelin-web/dist
zeppelin-web/.tmp
zeppelin-web/src/fonts/Roboto*
zeppelin-web/src/fonts/Source-Code-Pro*
zeppelin-web/src/fonts/Patua-One*
zeppelin-web/.sass-cache
zeppelin-web/bower_components
**nbproject/
**node/
#R
# R
/r/lib/
.Rhistory
# project level
/logs/
/run/
/metastore_db/
**/metastore_db/
/*.log
/jobs/
/zan-repo/
@ -79,7 +84,7 @@ Thumbs.db
.project
.settings/
#intelliJ IDEA project files
# intelliJ IDEA project files
.idea/
*.iml

View file

@ -20,6 +20,7 @@ sudo: false
cache:
directories:
- .spark-dist
- ${HOME}/.m2/repository/.cache/maven-download-plugin
addons:
apt:
@ -32,9 +33,13 @@ addons:
matrix:
include:
# Test all modules
# Test all modules with scala 2.10
- jdk: "oraclejdk7"
env: SPARK_VER="1.6.1" HADOOP_VER="2.3" PROFILE="-Pspark-1.6 -Pr -Phadoop-2.3 -Ppyspark -Psparkr -Pscalding" BUILD_FLAG="package -Pbuild-distr" TEST_FLAG="verify -Pusing-packaged-distr" TEST_PROJECTS=""
env: SPARK_VER="1.6.1" HADOOP_VER="2.3" PROFILE="-Pspark-1.6 -Pr -Phadoop-2.3 -Ppyspark -Psparkr -Pscalding -Pexamples" BUILD_FLAG="package -Dscala-2.10 -Pbuild-distr" TEST_FLAG="verify -Pusing-packaged-distr" TEST_PROJECTS=""
# Test all modules with scala 2.11
- jdk: "oraclejdk7"
env: SPARK_VER="1.6.1" HADOOP_VER="2.3" PROFILE="-Pspark-1.6 -Pr -Phadoop-2.3 -Ppyspark -Psparkr -Pscalding -Pexamples -Pscala-2.11" BUILD_FLAG="package -Dscala-2.11 -Pbuild-distr" TEST_FLAG="verify -Pusing-packaged-distr" TEST_PROJECTS=""
# Test spark module for 1.5.2
- jdk: "oraclejdk7"
@ -58,16 +63,15 @@ matrix:
# Test selenium with spark module for 1.6.1
- jdk: "oraclejdk7"
env: TEST_SELENIUM="true" SPARK_VER="1.6.1" HADOOP_VER="2.3" PROFILE="-Pspark-1.6 -Phadoop-2.3 -Ppyspark" BUILD_FLAG="package -DskipTests" TEST_FLAG="verify" TEST_PROJECTS="-pl zeppelin-interpreter,zeppelin-zengine,zeppelin-server,zeppelin-display,spark-dependencies,spark -Dtest=org.apache.zeppelin.AbstractFunctionalSuite -DfailIfNoTests=false"
env: TEST_SELENIUM="true" SPARK_VER="1.6.1" HADOOP_VER="2.3" PROFILE="-Pspark-1.6 -Phadoop-2.3 -Ppyspark -Pexamples" BUILD_FLAG="package -DskipTests" TEST_FLAG="verify" TEST_PROJECTS="-pl zeppelin-interpreter,zeppelin-zengine,zeppelin-server,zeppelin-display,spark-dependencies,spark -Dtest=org.apache.zeppelin.AbstractFunctionalSuite -DfailIfNoTests=false"
before_install:
- "ls -la .spark-dist"
- "ls -la .spark-dist ${HOME}/.m2/repository/.cache/maven-download-plugin"
- mkdir -p ~/R
- echo 'R_LIBS=~/R' > ~/.Renviron
- R -e "install.packages('knitr', repos = 'http://cran.us.r-project.org', lib='~/R')"
- export R_LIBS='~/R'
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1600x1024x16"
install:
- mvn $BUILD_FLAG $PROFILE -B
@ -81,7 +85,6 @@ before_script:
script:
- mvn $TEST_FLAG $PROFILE -B $TEST_PROJECTS
after_success:
- echo "Travis exited with ${TRAVIS_TEST_RESULT}"
@ -95,4 +98,3 @@ after_failure:
after_script:
- ./testing/stopSparkCluster.sh $SPARK_VER $HADOOP_VER

View file

@ -1,6 +1,6 @@
# How to contribute
**Zeppelin** is [Apache2 License](https://github.com/apache/incubator-zeppelin/blob/master/CONTRIBUTING.md) Software.
**Zeppelin** is [Apache2 License](https://github.com/apache/zeppelin/blob/master/CONTRIBUTING.md) Software.
Contributing to Zeppelin (Source code, Documents, Image, Website) means you agree to the Apache2 License.
1. Make sure your issue is not already in the [Jira issue tracker](https://issues.apache.org/jira/browse/ZEPPELIN)
@ -17,7 +17,7 @@ In order to make the review process easier, please follow this template when mak
```
### What is this PR for?
A few sentences describing the overall goals of the pull request's commits.
First time? Check out the contributing guide - https://github.com/apache/incubator-zeppelin/blob/master/CONTRIBUTING.md
First time? Check out the contributing guide - https://github.com/apache/zeppelin/blob/master/CONTRIBUTING.md
### What type of PR is it?
[Bug Fix | Improvement | Feature | Documentation | Hot Fix | Refactoring]
@ -58,7 +58,7 @@ You can also test and review a particular Pull Request. Here are two useful ways
* Another way is using [github/hub](https://github.com/github/hub).
```
hub checkout https://github.com/apache/incubator-zeppelin/pull/[# of PR]
hub checkout https://github.com/apache/zeppelin/pull/[# of PR]
```
The above two methods will help you test and review Pull Requests.
@ -91,8 +91,8 @@ Here are some things you will need to build and test Zeppelin.
### Software Configuration Management (SCM)
Zeppelin uses Git for its SCM system. `http://git.apache.org/incubator-zeppelin.git` you'll need git client installed in your development machine.
For write access, `https://git-wip-us.apache.org/repos/asf/incubator-zeppelin.git`
Zeppelin uses Git for its SCM system. `http://git.apache.org/zeppelin.git` you'll need git client installed in your development machine.
For write access, `https://git-wip-us.apache.org/repos/asf/zeppelin.git`
### Integrated Development Environment (IDE)
@ -109,8 +109,6 @@ The top-level pom.xml describes the basic project structure. Currently Zeppelin
<module>markdown</module>
<module>angular</module>
<module>shell</module>
<module>hive</module>
<module>tajo</module>
<module>flink</module>
<module>ignite</module>
<module>lens</module>
@ -121,12 +119,12 @@ The top-level pom.xml describes the basic project structure. Currently Zeppelin
### Web Project Contribution Guidelines
If you plan on making a contribution to Zeppelin's WebApplication,
please check [its own contribution guidelines](https://github.com/apache/incubator-zeppelin/blob/master/zeppelin-web/CONTRIBUTING.md)
please check [its own contribution guidelines](https://github.com/apache/zeppelin/blob/master/zeppelin-web/CONTRIBUTING.md)
### Code convention
We are following Google Code style:
* [Java style](http://google-styleguide.googlecode.com/svn/trunk/javaguide.html)
* [Shell style](https://google-styleguide.googlecode.com/svn/trunk/shell.xml)
* [Java style](https://google.github.io/styleguide/javaguide.html)
* [Shell style](https://google.github.io/styleguide/shell.xml)
Check style report location are in `${submodule}/target/site/checkstyle.html`
Test coverage report location are in `${submodule}/target/site/cobertura/index.html`
@ -138,31 +136,31 @@ To build the code, install
* Apache Maven
## Getting the source code
First of all, you need the Zeppelin source code. The official location for Zeppelin is [http://git.apache.org/incubator-zeppelin.git](http://git.apache.org/incubator-zeppelin.git).
First of all, you need the Zeppelin source code. The official location for Zeppelin is [http://git.apache.org/zeppelin.git](http://git.apache.org/zeppelin.git).
### git access
Get the source code on your development machine using git.
```
git clone git://git.apache.org/incubator-zeppelin.git zeppelin
git clone git://git.apache.org/zeppelin.git zeppelin
```
You may also want to develop against a specific branch. For example, for branch-0.5.6
```
git clone -b branch-0.5.6 git://git.apache.org/incubator-zeppelin.git zeppelin
git clone -b branch-0.5.6 git://git.apache.org/zeppelin.git zeppelin
```
or with write access
```
git clone https://git-wip-us.apache.org/repos/asf/incubator-zeppelin.git
git clone https://git-wip-us.apache.org/repos/asf/zeppelin.git
```
### Fork repository
If you want not only build Zeppelin but also make change, then you need fork Zeppelin github mirror repository (https://github.com/apache/incubator-zeppelin) and make pull request.
If you want not only build Zeppelin but also make change, then you need fork Zeppelin github mirror repository (https://github.com/apache/zeppelin) and make pull request.
## Build
@ -193,11 +191,11 @@ Zeppelin has 3 types of tests:
2. Integration Tests: The integration tests run after all modules are build. The integration tests launch an instance of Zeppelin server. ZeppelinRestApiTest is an example integration test.
3. GUI integration tests: These tests validate the Zeppelin UI elements. These tests require a running Zeppelin server and launches a web browser to validate Notebook UI elements like Notes and their execution. See ZeppelinIT as an example.
Currently the GUI integration tests are not run in the Maven and are only run in the CI environment when the pull request is submitted to github. Make sure to watch the [CI results] (https://travis-ci.org/apache/incubator-zeppelin/pull_requests) for your pull request.
Currently the GUI integration tests are not run in the Maven and are only run in the CI environment when the pull request is submitted to github. Make sure to watch the [CI results] (https://travis-ci.org/apache/zeppelin/pull_requests) for your pull request.
## Continuous Integration
Zeppelin uses Travis for CI. In the project root there is .travis.yml that configures CI and [publishes CI results] (https://travis-ci.org/apache/incubator-zeppelin/builds)
Zeppelin uses Travis for CI. In the project root there is .travis.yml that configures CI and [publishes CI results] (https://travis-ci.org/apache/zeppelin/builds)
## Run Zeppelin server in development mode
@ -219,9 +217,12 @@ Server will be run on http://localhost:8080
## JIRA
Zeppelin manages it's issues in Jira. [https://issues.apache.org/jira/browse/ZEPPELIN](https://issues.apache.org/jira/browse/ZEPPELIN)
## Where to Start
You can find issues for [beginner](https://issues.apache.org/jira/issues/?jql=(labels%20%3D%20newbie%20or%20labels%3D%20beginner)%20and%20project%3DZeppelin)
## Stay involved
Everyone is welcome to join our mailing list:
* [users@zeppelin.incubator.apache.org](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-users/) is for usage questions, help, and announcements [ [subscribe](mailto:users-subscribe@zeppelin.incubator.apache.org?subject=send%20this%20email%20to%20subscribe), [unsubscribe](mailto:users-unsubscribe@zeppelin.incubator.apache.org?subject=send%20this%20email%20to%20unsubscribe), [archive](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-users/) ]
* [dev@zeppelin.incubator.apache.org](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-users/) is for people who want to contribute code to Zeppelin.[ [subscribe](mailto:dev-subscribe@zeppelin.incubator.apache.org?subject=send%20this%20email%20to%20subscribe), [unsubscribe](mailto:dev-unsubscribe@zeppelin.incubator.apache.org?subject=send%20this%20email%20to%20unsubscribe), [archive](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/) ]
* [commits@zeppelin.incubator.apache.org](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-commits/) is for commit messages and patches to Zeppelin. [ [subscribe](mailto:commits-subscribe@zeppelin.incubator.apache.org?subject=send%20this%20email%20to%20subscribe), [unsubscribe](mailto:commits-unsubscribe@zeppelin.incubator.apache.org?subject=send%20this%20email%20to%20unsubscribe), [archive](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-commits/) ]
* [users@zeppelin.apache.org](http://mail-archives.apache.org/mod_mbox/zeppelin-users/) is for usage questions, help, and announcements [ [subscribe](mailto:users-subscribe@zeppelin.apache.org?subject=send%20this%20email%20to%20subscribe), [unsubscribe](mailto:users-unsubscribe@zeppelin.apache.org?subject=send%20this%20email%20to%20unsubscribe), [archive](http://mail-archives.apache.org/mod_mbox/zeppelin-users/) ]
* [dev@zeppelin.apache.org](http://mail-archives.apache.org/mod_mbox/zeppelin-users/) is for people who want to contribute code to Zeppelin.[ [subscribe](mailto:dev-subscribe@zeppelin.apache.org?subject=send%20this%20email%20to%20subscribe), [unsubscribe](mailto:dev-unsubscribe@zeppelin.apache.org?subject=send%20this%20email%20to%20unsubscribe), [archive](http://mail-archives.apache.org/mod_mbox/zeppelin-dev/) ]
* [commits@zeppelin.apache.org](http://mail-archives.apache.org/mod_mbox/zeppelin-commits/) is for commit messages and patches to Zeppelin. [ [subscribe](mailto:commits-subscribe@zeppelin.apache.org?subject=send%20this%20email%20to%20subscribe), [unsubscribe](mailto:commits-unsubscribe@zeppelin.apache.org?subject=send%20this%20email%20to%20unsubscribe), [archive](http://mail-archives.apache.org/mod_mbox/zeppelin-commits/) ]

View file

@ -1,12 +0,0 @@
Apache Zeppelin is an effort undergoing incubation at the Apache Software
Foundation (ASF), sponsored by the Apache Incubator PMC.
Incubation is required of all newly accepted projects until a further
review indicates that the infrastructure, communications, and decision
making process have stabilized in a manner consistent with other
successful ASF projects.
While incubation status is not necessarily a reflection of the
completeness or stability of the code, it does indicate that the
project has yet to be fully endorsed by the ASF.

18
LICENSE
View file

@ -235,7 +235,13 @@ The text of each license is also included at licenses/LICENSE-[project]-[version
(The MIT License) jekyll-bootstrap 0.3.0 (https://github.com/plusjade/jekyll-bootstrap) - https://github.com/plusjade/jekyll-bootstrap
(The MIT License) jekyll 1.3.0 (http://jekyllrb.com/) - https://github.com/jekyll/jekyll/blob/v1.3.0/LICENSE
========================================================================
MIT-style licenses
========================================================================
The following components are provided under the MIT-style license. See project link for details.
The text of each license is also included at licenses/LICENSE-[project]-[version].txt.
(MIT Style) jekyll-table-of-contents (https://github.com/ghiculescu/jekyll-table-of-contents) - https://github.com/ghiculescu/jekyll-table-of-contents/blob/master/LICENSE.txt
========================================================================
Apache licenses
@ -256,4 +262,12 @@ The following components are provided under the BSD 3-Clause license. See file
r/src/main/scala/org/apache/zeppelin/rinterpreter/rscala/{Package.scala, RClient.scala}
(BSD 3 Clause) portions of Scala (http://www.scala-lang.org/download) - http://www.scala-lang.org/download/#License
r/src/main/scala/scala/Console.scala
r/src/main/scala/scala/Console.scala
========================================================================
BSD 2-Clause licenses
========================================================================
The following components are provided under the BSD 3-Clause license. See file headers and project links for details.
(BSD 2 Clause) portions of SQLLine (http://sqlline.sourceforge.net/) - http://sqlline.sourceforge.net/#license
jdbc/src/main/java/org/apache/zeppelin/jdbc/SqlCompleter.java

2
NOTICE
View file

@ -1,4 +1,4 @@
Apache Zeppelin (incubating)
Apache Zeppelin
Copyright 2015 - 2016 The Apache Software Foundation
This product includes software developed at

View file

@ -1,11 +1,11 @@
#Zeppelin
**Documentation:** [User Guide](http://zeppelin.incubator.apache.org/docs/latest/index.html)<br/>
**Mailing Lists:** [User and Dev mailing list](http://zeppelin.incubator.apache.org/community.html)<br/>
**Continuous Integration:** [![Build Status](https://secure.travis-ci.org/apache/incubator-zeppelin.png?branch=master)](https://travis-ci.org/apache/incubator-zeppelin) <br/>
**Contributing:** [Contribution Guide](https://github.com/apache/incubator-zeppelin/blob/master/CONTRIBUTING.md)<br/>
**Documentation:** [User Guide](http://zeppelin.apache.org/docs/latest/index.html)<br/>
**Mailing Lists:** [User and Dev mailing list](http://zeppelin.apache.org/community.html)<br/>
**Continuous Integration:** [![Build Status](https://secure.travis-ci.org/apache/zeppelin.png?branch=master)](https://travis-ci.org/apache/zeppelin) <br/>
**Contributing:** [Contribution Guide](https://github.com/apache/zeppelin/blob/master/CONTRIBUTING.md)<br/>
**Issue Tracker:** [Jira](https://issues.apache.org/jira/browse/ZEPPELIN)<br/>
**License:** [Apache 2.0](https://github.com/apache/incubator-zeppelin/blob/master/LICENSE)
**License:** [Apache 2.0](https://github.com/apache/zeppelin/blob/master/LICENSE)
**Zeppelin**, a web-based notebook that enables interactive data analytics. You can make beautiful data-driven, interactive and collaborative documents with SQL, Scala and more.
@ -15,7 +15,7 @@ Core feature:
* Built-in Apache Spark support
To know more about Zeppelin, visit our web site [http://zeppelin.incubator.apache.org](http://zeppelin.incubator.apache.org)
To know more about Zeppelin, visit our web site [http://zeppelin.apache.org](http://zeppelin.apache.org)
## Requirements
* Git
@ -39,25 +39,46 @@ sudo apt-get install libfontconfig
```
#### Proxy settings (optional)
If you are behind a corporate Proxy with NTLM authentication you can use [Cntlm Authentication Proxy](http://cntlm.sourceforge.net/) .
Before build start, run these commands from shell.
First of all, set your proxy configuration on Maven `settings.xml`.
```
<settings>
<proxies>
<proxy>
<id>proxy-http</id>
<active>true</active>
<protocol>http</protocol>
<host>localhost</host>
<port>3128</port>
<!-- <username>usr</username>
<password>pwd</password> -->
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
<proxy>
<id>proxy-https</id>
<active>true</active>
<protocol>https</protocol>
<host>localhost</host>
<port>3128</port>
<!-- <username>usr</username>
<password>pwd</password> -->
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
</proxies>
</settings>
```
Then, run these commands from shell.
```
export http_proxy=http://localhost:3128
export https_proxy=http://localhost:3128
export HTTP_PROXY=http://localhost:3128
export HTTPS_PROXY=http://localhost:3128
npm config set proxy http://localhost:3128
npm config set https-proxy http://localhost:3128
npm config set registry "http://registry.npmjs.org/"
npm config set strict-ssl false
npm cache clean
git config --global http.proxy http://localhost:3128
git config --global https.proxy http://localhost:3128
git config --global url."http://".insteadOf git://
```
After build is complete, run these commands to cleanup.
Cleanup: set `active false` in Maven `settings.xml` and run these commands.
```
npm config rm proxy
npm config rm https-proxy
@ -67,9 +88,8 @@ git config --global --unset url."http://".insteadOf
```
_Notes:_
- If you are on Windows replace `export` with `set` to set env variables
- Replace `localhost:3128` with standard pattern `http://user:pwd@host:port`
- Git configuration is needed because Bower use it for fetching from GitHub
- If you are behind NTLM proxy you can use [Cntlm Authentication Proxy](http://cntlm.sourceforge.net/).
- Replace `localhost:3128` with the standard pattern `http://user:pwd@host:port`.
#### Install maven
```
@ -162,8 +182,7 @@ enable 3rd party vendor repository (cloudera)
##### `-Pmapr[version]` (optional)
For the MapR Hadoop Distribution, these profiles will handle the Hadoop version. As MapR allows different versions of Spark to be installed, you should specify which version of Spark is installed on the cluster by adding a Spark profile (`-Pspark-1.2`, `-Pspark-1.3`, etc.) as needed.
For Hive, check the hive/pom.xml and adjust the version installed as well. The correct Maven
artifacts can be found for every version of MapR at http://doc.mapr.com
The correct Maven artifacts can be found for every version of MapR at http://doc.mapr.com
Available profiles are
@ -175,6 +194,13 @@ Available profiles are
-Pmapr51
```
#### -Pexamples (optional)
Bulid examples under zeppelin-examples directory
Here're some examples:
@ -196,7 +222,7 @@ mvn clean package -Pspark-1.5 -Pmapr50 -DskipTests
#### Ignite Interpreter
```sh
mvn clean package -Dignite.version=1.1.0-incubating -DskipTests
mvn clean package -Dignite.version=1.6.0 -DskipTests
```
#### Scalding Interpreter
@ -205,6 +231,7 @@ mvn clean package -Dignite.version=1.1.0-incubating -DskipTests
mvn clean package -Pscalding -DskipTests
```
### Configure
If you wish to configure Zeppelin option (like port number), configure the following files:
@ -260,6 +287,14 @@ And browse [localhost:8080](localhost:8080) in your browser.
For configuration details check __`./conf`__ subdirectory.
### Building for Scala 2.11
To produce a Zeppelin package compiled with Scala 2.11, use the -Pscala-2.11 profile:
```
mvn clean package -Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Pscala-2.11 -DskipTests clean install
```
### Package
To package the final distribution including the compressed archive, run:
@ -288,4 +323,4 @@ mvn verify
mvn verify -P using-packaged-distr
```
[![Analytics](https://ga-beacon.appspot.com/UA-45176241-4/apache/incubator-zeppelin/README.md?pixel)](https://github.com/igrigorik/ga-beacon)
[![Analytics](https://ga-beacon.appspot.com/UA-45176241-4/apache/zeppelin/README.md?pixel)](https://github.com/igrigorik/ga-beacon)

View file

@ -14,10 +14,10 @@ limitations under the License.
# Shiro Authentication
To connect to Zeppelin, users will be asked to enter their credentials. Once logged, a user has access to all notes including other users notes.
This a a first step toward full security as implemented by this pull request (https://github.com/apache/incubator-zeppelin/pull/53).
This a a first step toward full security as implemented by this pull request (https://github.com/apache/zeppelin/pull/53).
# Security setup
1. Secure the HTTP channel: Comment the line "/** = anon" and uncomment the line "/** = authcBasic" in the file conf/shiro.ini. Read more about he shiro.ini file format at the following URL http://shiro.apache.org/configuration.html#Configuration-INISections.
1. Secure the HTTP channel: Comment the line "/** = anon" and uncomment the line "/** = authc" in the file conf/shiro.ini. Read more about he shiro.ini file format at the following URL http://shiro.apache.org/configuration.html#Configuration-INISections.
2. Secure the Websocket channel : Set to property "zeppelin.anonymous.allowed" to "false" in the file conf/zeppelin-site.xml. You can start by renaming conf/zeppelin-site.xml.template to conf/zeppelin-site.xml
3. Start Zeppelin : bin/zeppelin.sh
4. point your browser to http://localhost:8080

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.7.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-alluxio</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.7.0-SNAPSHOT</version>
<name>Zeppelin: Alluxio interpreter</name>
<url>http://www.apache.org</url>
@ -132,15 +132,6 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>

View file

@ -28,6 +28,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -67,15 +68,6 @@ public class AlluxioInterpreter extends Interpreter {
alluxioMasterPort = property.getProperty(ALLUXIO_MASTER_PORT);
}
static {
Interpreter.register("alluxio", "alluxio",
AlluxioInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add(ALLUXIO_MASTER_HOSTNAME, "localhost", "Alluxio master hostname")
.add(ALLUXIO_MASTER_PORT, "19998", "Alluxio master port")
.build());
}
@Override
public void open() {
logger.info("Starting Alluxio shell to connect to " + alluxioMasterHostname +
@ -115,14 +107,14 @@ public class AlluxioInterpreter extends Interpreter {
System.setOut(ps);
for (String command : commands) {
int commandResuld = 1;
int commandResult = 1;
String[] args = splitAndRemoveEmpty(command, " ");
if (args.length > 0 && args[0].equals("help")) {
System.out.println(getCommandList());
} else {
commandResuld = fs.run(args);
commandResult = fs.run(args);
}
if (commandResuld != 0) {
if (commandResult != 0) {
isSuccess = false;
break;
} else {
@ -174,16 +166,17 @@ public class AlluxioInterpreter extends Interpreter {
}
@Override
public List<String> completion(String buf, int cursor) {
public List<InterpreterCompletion> completion(String buf, int cursor) {
String[] words = splitAndRemoveEmpty(splitAndRemoveEmpty(buf, "\n"), " ");
String lastWord = "";
if (words.length > 0) {
lastWord = words[ words.length - 1 ];
}
ArrayList<String> voices = new ArrayList<String>();
List<InterpreterCompletion> voices = new LinkedList<>();
for (String command : keywords) {
if (command.startsWith(lastWord)) {
voices.add(command);
voices.add(new InterpreterCompletion(command, command));
}
}
return voices;

View file

@ -0,0 +1,21 @@
[
{
"group": "alluxio",
"name": "alluxio",
"className": "org.apache.zeppelin.alluxio.AlluxioInterpreter",
"properties": {
"alluxio.master.hostname": {
"envName": "ALLUXIO_MASTER_HOSTNAME",
"propertyName": "alluxio.master.hostname",
"defaultValue": "localhost",
"description": "Alluxio master hostname"
},
"alluxio.master.port": {
"envName": "ALLUXIO_MASTER_PORT",
"propertyName": "alluxio.master.port",
"defaultValue": "19998",
"description": "Alluxio master port"
}
}
}
]

View file

@ -31,6 +31,7 @@ import alluxio.client.WriteType;
import alluxio.client.file.URIStatus;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.junit.*;
import alluxio.Constants;
@ -76,25 +77,40 @@ public class AlluxioInterpreterTest {
@Test
public void testCompletion() {
List<String> expectedResultOne = Arrays.asList("cat", "chgrp",
"chmod", "chown", "copyFromLocal", "copyToLocal", "count",
"createLineage");
List<String> expectedResultTwo = Arrays.asList("copyFromLocal",
"copyToLocal", "count");
List<String> expectedResultThree = Arrays.asList("copyFromLocal", "copyToLocal");
List<String> expectedResultNone = new ArrayList<String>();
List expectedResultOne = Arrays.asList(
new InterpreterCompletion("cat", "cat"),
new InterpreterCompletion("chgrp", "chgrp"),
new InterpreterCompletion("chmod", "chmod"),
new InterpreterCompletion("chown", "chown"),
new InterpreterCompletion("copyFromLocal", "copyFromLocal"),
new InterpreterCompletion("copyToLocal", "copyToLocal"),
new InterpreterCompletion("count", "count"),
new InterpreterCompletion("createLineage", "createLineage"));
List expectedResultTwo = Arrays.asList(
new InterpreterCompletion("copyFromLocal", "copyFromLocal"),
new InterpreterCompletion("copyToLocal", "copyToLocal"),
new InterpreterCompletion("count", "count"));
List expectedResultThree = Arrays.asList(
new InterpreterCompletion("copyFromLocal", "copyFromLocal"),
new InterpreterCompletion("copyToLocal", "copyToLocal"));
List expectedResultNone = new ArrayList<String>();
List<String> resultOne = alluxioInterpreter.completion("c", 0);
List<String> resultTwo = alluxioInterpreter.completion("co", 0);
List<String> resultThree = alluxioInterpreter.completion("copy", 0);
List<String> resultNotMatch = alluxioInterpreter.completion("notMatch", 0);
List<String> resultAll = alluxioInterpreter.completion("", 0);
List<InterpreterCompletion> resultOne = alluxioInterpreter.completion("c", 0);
List<InterpreterCompletion> resultTwo = alluxioInterpreter.completion("co", 0);
List<InterpreterCompletion> resultThree = alluxioInterpreter.completion("copy", 0);
List<InterpreterCompletion> resultNotMatch = alluxioInterpreter.completion("notMatch", 0);
List<InterpreterCompletion> resultAll = alluxioInterpreter.completion("", 0);
Assert.assertEquals(expectedResultOne, resultOne);
Assert.assertEquals(expectedResultTwo, resultTwo);
Assert.assertEquals(expectedResultThree, resultThree);
Assert.assertEquals(expectedResultNone, resultNotMatch);
Assert.assertEquals(alluxioInterpreter.keywords, resultAll);
List allCompletionList = new ArrayList<>();
for (InterpreterCompletion ic : resultAll) {
allCompletionList.add(ic.getName());
}
Assert.assertEquals(alluxioInterpreter.keywords, allCompletionList);
}
@Test

View file

@ -22,16 +22,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.7.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-angular</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.7.0-SNAPSHOT</version>
<name>Zeppelin: Angular interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<dependencies>
<dependency>
@ -60,15 +60,6 @@
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>

View file

@ -26,6 +26,7 @@ import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.InterpreterResult.Type;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
@ -69,8 +70,8 @@ public class AngularInterpreter extends Interpreter {
}
@Override
public List<String> completion(String buf, int cursor) {
return new LinkedList<String>();
public List<InterpreterCompletion> completion(String buf, int cursor) {
return new LinkedList<>();
}
@Override

45
bin/install-interpreter.sh Executable file
View file

@ -0,0 +1,45 @@
#!/bin/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.
#
# Run Zeppelin
#
bin=$(dirname "${BASH_SOURCE-$0}")
bin=$(cd "${bin}">/dev/null; pwd)
. "${bin}/common.sh"
ZEPPELIN_INSTALL_INTERPRETER_MAIN=org.apache.zeppelin.interpreter.install.InstallInterpreter
ZEPPELIN_LOGFILE="${ZEPPELIN_LOG_DIR}/install-interpreter.log"
JAVA_OPTS+=" -Dzeppelin.log.file=${ZEPPELIN_LOGFILE}"
if [[ -d "${ZEPPELIN_HOME}/zeppelin-zengine/target/classes" ]]; then
ZEPPELIN_CLASSPATH+=":${ZEPPELIN_HOME}/zeppelin-zengine/target/classes"
fi
addJarInDir "${ZEPPELIN_HOME}/zeppelin-server/target/lib"
if [[ -d "${ZEPPELIN_HOME}/zeppelin-interpreter/target/classes" ]]; then
ZEPPELIN_CLASSPATH+=":${ZEPPELIN_HOME}/zeppelin-interpreter/target/classes"
fi
addJarInDir "${ZEPPELIN_HOME}/zeppelin-interpreter/target/lib"
addJarInDir "${ZEPPELIN_HOME}/lib"
CLASSPATH+=":${ZEPPELIN_CLASSPATH}"
$ZEPPELIN_RUNNER $JAVA_OPTS -cp $CLASSPATH $ZEPPELIN_INSTALL_INTERPRETER_MAIN ${@}

View file

@ -22,30 +22,27 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.7.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-cassandra</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<name>Zeppelin: Cassandra</name>
<version>0.7.0-SNAPSHOT</version>
<name>Zeppelin: Apache Cassandra interpreter</name>
<description>Zeppelin cassandra support</description>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<cassandra.driver.version>3.0.0-rc1</cassandra.driver.version>
<cassandra.driver.version>3.0.1</cassandra.driver.version>
<snappy.version>1.0.5.4</snappy.version>
<lz4.version>1.3.0</lz4.version>
<scala.version>2.10.4</scala.version>
<scala.binary.version>2.10</scala.binary.version>
<commons-lang.version>3.3.2</commons-lang.version>
<scalate.version>1.7.1</scalate.version>
<cassandra.guava.version>16.0.1</cassandra.guava.version>
<!--TEST-->
<scalatest.version>2.2.4</scalatest.version>
<junit.version>4.12</junit.version>
<achilles.version>3.2.4-Zeppelin</achilles.version>
<assertj.version>1.7.0</assertj.version>
@ -173,6 +170,7 @@
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>compile</id>
@ -230,15 +228,6 @@
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>

View file

@ -23,6 +23,7 @@ import org.apache.zeppelin.interpreter.Interpreter;
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterPropertyBuilder;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
@ -110,7 +111,7 @@ public class CassandraInterpreter extends Interpreter {
public static final String DEFAULT_PORT = "9042";
public static final String DEFAULT_CLUSTER = "Test Cluster";
public static final String DEFAULT_KEYSPACE = "system";
public static final String DEFAULT_PROTOCOL_VERSION = "3";
public static final String DEFAULT_PROTOCOL_VERSION = "4";
public static final String DEFAULT_COMPRESSION = "NONE";
public static final String DEFAULT_CREDENTIAL = "none";
public static final String DEFAULT_POLICY = "DEFAULT";
@ -139,7 +140,7 @@ public class CassandraInterpreter extends Interpreter {
public static final String LOGGING_DOWNGRADING_RETRY = "LOGGING_DOWNGRADING";
public static final String LOGGING_FALLTHROUGH_RETRY = "LOGGING_FALLTHROUGH";
public static final List<String> NO_COMPLETION = new ArrayList<>();
public static final List NO_COMPLETION = new ArrayList<>();
InterpreterLogic helper;
Cluster cluster;
@ -159,7 +160,7 @@ public class CassandraInterpreter extends Interpreter {
"IP address). Default = localhost. Ex: '192.168.0.12,node2,node3'")
.add(CASSANDRA_PORT, DEFAULT_PORT, "Cassandra native port. Default = 9042")
.add(CASSANDRA_PROTOCOL_VERSION, DEFAULT_PROTOCOL_VERSION,
"Cassandra protocol version. Default = 3")
"Cassandra protocol version. Default = 4")
.add(CASSANDRA_CLUSTER_NAME, DEFAULT_CLUSTER, "Cassandra cluster name. " +
"Default = 'Test Cluster'")
.add(CASSANDRA_KEYSPACE_NAME, DEFAULT_KEYSPACE, "Cassandra keyspace name. " +
@ -311,7 +312,7 @@ public class CassandraInterpreter extends Interpreter {
@Override
public FormType getFormType() {
return FormType.NATIVE;
return FormType.SIMPLE;
}
@Override
@ -320,7 +321,7 @@ public class CassandraInterpreter extends Interpreter {
}
@Override
public List<String> completion(String buf, int cursor) {
public List<InterpreterCompletion> completion(String buf, int cursor) {
return NO_COMPLETION;
}

View file

@ -103,12 +103,12 @@
<ul class="dropdown-menu">
<li>
<a role="button">
<span class="text-info">Version <strong>2.0</strong></span>
<span class="text-info">Version <strong>3.0</strong></span>
</a>
</li>
<li>
<a role="button">
<span class="text-info">Java Driver Version <strong>3.0.0-rc1</strong></span>
<span class="text-info">Java Driver Version <strong>3.0.1</strong></span>
</a>
</li>
<li>
@ -215,6 +215,14 @@
<tr><th>Cassandra version</th><th>Documentation</th></tr>
</thead>
<tbody>
<tr>
<td><strong>3.x</strong></td>
<td>
<a href="http://docs.datastax.com/en/cql/3.3/cql/cqlIntro.html" target="_blank">
http://docs.datastax.com/en/cql/3.3/cql/cqlIntro.html
</a>
</td>
</tr>
<tr>
<td><strong>2.2</strong></td>
<td>
@ -464,6 +472,11 @@
<td><strong>@fetchSize=<em>int value</em></strong></td>
<td>Apply the given fetch size to all queries in the paragraph</td>
</tr>
<tr>
<td>Request Timeout</td>
<td><strong>@requestTimeOut=<em>int value</em></strong></td>
<td>Apply the given request timeout <strong>in millisecs</strong> to all queries in the paragraph</td>
</tr>
</tbody>
</table>
<br/>
@ -506,6 +519,10 @@
<td>Fetch Size</td>
<td>Any integer value</td>
</tr>
<tr>
<td>Request Timeout</td>
<td>Any integer value</td>
</tr>
</tbody>
</table>
<br/>
@ -526,19 +543,19 @@
);
TRUNCATE spark_demo.ts;
# Timestamp in the past
// Timestamp in the past
@timestamp=10
# Force timestamp directly in the first insert
// Force timestamp directly in the first insert
INSERT INTO spark_demo.ts(key,value) VALUES(1,'first insert') USING TIMESTAMP 100;
# Select some data to make the clock turn
// Select some data to make the clock turn
SELECT * FROM spark_demo.albums LIMIT 100;
# Now insert using the timestamp parameter set at the beginning(10)
// Now insert using the timestamp parameter set at the beginning(10)
INSERT INTO spark_demo.ts(key,value) VALUES(1,'second insert');
# Check for the result. You should see 'first insert'
// Check for the result. You should see 'first insert'
SELECT value FROM spark_demo.ts WHERE key=1;
</pre>
</div>
@ -599,13 +616,13 @@
<div class="col-md-10 col-md-offset-1">
<pre>
@prepare[statement_name]=...
@prepare[statement-name]=...
@bind[statement_name]=text, 1223, 2015-07-30 12:00:01, null, true, [list_item1, list_item2]
@bind[statement-name]=text, 1223, 2015-07-30 12:00:01, null, true, [list_item1, list_item2]
@bind[statement_name_with_no_bound_value]
@bind[statement-name-with-no-bound-value]
@remove_prepare[statement_name]
@remove_prepare[statement-name]
</pre>
</div>
@ -615,10 +632,10 @@
<h3>II @prepare</h3>
<br/>
<p>
You can use the syntax "<strong>@prepare[statement_name]=SELECT ...</strong>" to create a prepared statement.
The <em>statement_name</em> is mandatory because the interpreter prepares the given statement with the
You can use the syntax "<strong>@prepare[statement-name]=SELECT ...</strong>" to create a prepared statement.
The <em>statement-name</em> is mandatory because the interpreter prepares the given statement with the
Java driver and saves the generated prepared statement in an internal map, using the provided
<em>statement_name</em> as search key.
<em>statement-name</em> as search key.
<br/><br/>
<div class="alert alert-info">
Please note that this internal prepared statement map is shared with <strong>all notebooks</strong>
@ -626,7 +643,7 @@
</div>
<br/>
<div class="alert alert-warning">
If the interpreter encounters many @prepare for the <strong>same statement_name</strong> (key),
If the interpreter encounters many @prepare for the <strong>same statement-name</strong> (key),
only the <strong>first</strong> statement will be taken into account.
</div>
<br/>
@ -645,7 +662,7 @@
<br/>
For the above example, the prepared statement is <strong>"SELECT * FROM spark_demo.albums LIMIT ?"</strong>.
<em>"SELECT * FROM spark_demo.artists LIMIT ?"</em> is ignored because an entry already exists in the
<strong>"SELECT * FROM spark_demo.artists LIMIT ?"</strong> is ignored because an entry already exists in the
prepared statements map with the key <strong>select</strong>.
<br/><br/>
In the context of Zeppelin, a notebook can be scheduled to be executed at regular interval,
@ -712,7 +729,7 @@
<h3>IV @remove_prepare</h3>
<br/>
<p>
To avoid for a prepared statement to stay forever in the prepared statement map, you can use the <strong>@remove_prepare[statement_name]</strong> syntax
To avoid for a prepared statement to stay forever in the prepared statement map, you can use the <strong>@remove_prepare[statement-name]</strong> syntax
to remove it. Removing a non-existing prepared statement yields no error.
</p>
</div>
@ -735,16 +752,22 @@
<div class="panel panel-default">
<div class="panel-body">
<p>
Instead of hard-coding your CQL queries, it is possible to use the mustache syntax (<strong>{{ }}</strong>)
to inject simple value or multiple choices forms.
Instead of hard-coding your CQL queries, it is possible to use <strong>
<a href="http://zeppelin.apache.org/docs/0.6.0-SNAPSHOT/manual/dynamicform.html" target="_blank">Zeppelin dynamic form</a>
</strong> syntax to inject simple value or multiple choices forms.
The legacy mustache syntax ( <strong>{{ }}</strong> ) to bind input text and select form is still supported but is deprecated and will be removed in future releases.
<br/><br/>
<h6> -- Legacy syntax -- </h6>
The syntax for simple parameter is: <strong>{{input_Label=default value}}</strong>.
The default value is mandatory because the first time the paragraph is executed,
we launch the CQL query before rendering the form so at least one value should be provided.
<br/><br/>
The syntax for multiple choices parameter is: <strong>{{input_Label=value1 | value2 | … | valueN }}</strong>.
By default the first choice is used for CQL query the first time the paragraph is executed.
<h6> -- End legacy syntax -- </h6>
<br/><br/>
Example:
<br/>
@ -755,8 +778,8 @@
#Secondary index on performer style
SELECT name, country, performer
FROM spark_demo.performers
WHERE name='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}'
AND styles CONTAINS '{{style=Rock}}';
WHERE name='\${performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}'
AND styles CONTAINS '\${style=Rock}';
</pre>
</div>
@ -766,13 +789,13 @@
In the above example, the first CQL query will be executed for <em>performer='Sheryl Crow'</em>
AND <em>style='Rock'</em>. For subsequent queries, you can change the value directly using the form.
Please note that we enclosed the {{ }} block between simple quotes (') because Cassandra expects a String here.
We could have also use the <strong>{{style='Rock'}}</strong> syntax but this time, the value
We could have also use the <strong>\${style='Rock'}</strong> syntax but this time, the value
displayed on the form is <em>'Rock'</em> and not <em>Rock</em>.
<br/><br/>
<div class="alert alert-info">
It is also possible to use dynamic forms for <strong>prepared statements</strong>: <br/>
<strong>@bind[select]=='{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}}', '{{style=Rock}}'</strong>
<strong>@bind[select]=='\${performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia}', '\${style=Rock}'</strong>
</div>
</pre>
</p>
@ -892,7 +915,7 @@
</tr>
<tr>
<td>cassandra.protocol.version</td>
<td><strong>3</strong></td>
<td><strong>4</strong></td>
</tr>
<tr>
<td>cassandra.query.default.consistency</td>
@ -947,20 +970,35 @@
<div id="${sharedStatesId}" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
It is possible to execute many paragraphs in parallel. However, at the back-end side, were still using synchronous queries. <em>Asynchronous execution</em> is only possible when it is possible to return a <strong>Future</strong> value in the <strong>InterpreterResult</strong>. It may be an interesting proposal for the <strong>Zeppelin</strong> project.
<br/>
Another caveat is that the same <strong>com.datastax.driver.core.Session</strong> object is used for <strong>all</strong> notebooks and paragraphs. Consequently, if you use the <em>USE keyspace name;</em> statement to log into a keyspace, it will change the keyspace for <strong>all current users</strong> of the Cassandra interpreter because we only create 1 <strong>com.datastax.driver.core.Session</strong> object per instance of <strong>Cassandra</strong> interpreter.
<br/>
The same remark does apply to the <strong>prepared statement hash map</strong>, it is shared by <strong>all users</strong> using the same instance of <strong>Cassandra</strong> interpreter.
<br/><br/>
Recently, <strong>Zeppelin</strong> allows you to choose the level of isolation for your interpreters (see
<strong><a href="http://zeppelin.apache.org/docs/0.6.0-SNAPSHOT/manual/interpreters.html" target="_blank">Interpreter Binding Mode</a></strong> ).
<br/><br/>
Long story short, you have 3 available bindings:
<ul>
<li><strong>shared</strong> : <em>same JVM</em> and <em>same Interpreter instance</em> for all notes</li>
<li><strong>scoped</strong> : <em>same JVM</em> but <em>different Interpreter instances</em>, one for each note</li>
<li><strong>isolated</strong> : <em>different JVM</em> running a <em>single Interpreter instance</em>, one JVM for each note</li>
</ul>
<br/>
Until <strong>Zeppelin</strong> offers a real multi-users separation, there is a work-around to segregate user environment and states: <em>create different Cassandra interpreter instances</em>
<br/>
<ol>
<li>First go to the <strong>Interpreter</strong> menu and click on the <strong>Create</strong> button</li>
<li>In the interpreter creation form, put <strong>cass-instance2</strong> as <strong>Name</strong> and select the <strong>cassandra</strong> in the interpreter drop-down list</li>
<li>Click on <strong>Save</strong> to create the new interpreter instance. Now you should be able to see it in the interpreter list</li>
<li>Go back to your notebook and click on the <strong>Gear</strong> icon to configure interpreter bindings. You should be able to see and select the <strong>cass-instance2</strong> interpreter instance in the available interpreter list instead of the standard <strong>cassandra</strong> instance</li>
</ol>
</div>
Using the <strong>shared</strong> binding, the same <code>com.datastax.driver.core.Session</code> object is used for all notes and paragraphs.
Consequently, if you use the <strong>USE keyspace name;</strong> statement to log into a keyspace,
it will change the keyspace for all current users of the Cassandra interpreter because we only create 1
<code>com.datastax.driver.core.Session</code> object per instance of Cassandra interpreter.
<br/><br/>
The same remark does apply to the <strong>prepared statement hash map</strong>, it is shared by all users using the same instance of Cassandra interpreter.
<br/><br/>
When using <strong>scoped</strong> binding, in the <em>same JVM</em> <strong>Zeppelin</strong> will create multiple instances of the Cassandra interpreter,
thus multiple <code>com.datastax.driver.core.Session</code> objects.
<strong>Beware of resource and memory usage using this binding !</strong>
<br/><br/>
The <strong>isolated</strong> mode is the most extreme and will create as many JVM/<code>com.datastax.driver.core.Session</code> object as there are distinct notes.
</div>
</div>
</div>
@ -974,6 +1012,20 @@
</div>
<div id="${changelogId}" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<strong>3.0</strong>&nbsp;:
<br/>
<ul>
<li>Update documentation</li>
<li>Update interactive documentation</li>
<li>Add support for binary protocol <strong>V4</strong></li>
<li>Implement new <code>@requestTimeOut</code> runtime option</li>
<li>Upgrade Java driver version to <strong>3.0.1</strong></li>
<li>Allow interpreter to add dynamic forms programmatically when using FormType.SIMPLE</li>
<li>Allow dynamic form using default Zeppelin syntax</li>
<li>Fixing typo on FallThroughPolicy</li>
<li>Look for data in AngularObjectRegistry before creating dynamic form</li>
<li>Add missing support for <code>ALTER</code> statements</li>
</ul>
<strong>2.0</strong>&nbsp;:
<br/>
<ul>

View file

@ -29,6 +29,7 @@ import com.datastax.driver.core._
import com.datastax.driver.core.exceptions.DriverException
import com.datastax.driver.core.policies.{LoggingRetryPolicy, FallthroughRetryPolicy, DowngradingConsistencyRetryPolicy, Policies}
import org.apache.zeppelin.cassandra.TextBlockHierarchy._
import org.apache.zeppelin.display.AngularObjectRegistry
import org.apache.zeppelin.display.Input.ParamOption
import org.apache.zeppelin.interpreter.InterpreterResult.Code
import org.apache.zeppelin.interpreter.{InterpreterException, InterpreterResult, InterpreterContext}
@ -41,17 +42,20 @@ import scala.collection.mutable.ArrayBuffer
/**
* Value object to store runtime query parameters
* @param consistency consistency level
*
* @param consistency consistency level
* @param serialConsistency serial consistency level
* @param timestamp timestamp
* @param retryPolicy retry policy
* @param fetchSize query fetch size
* @param requestTimeOut request time out in millisecs
*/
case class CassandraQueryOptions(consistency: Option[ConsistencyLevel],
serialConsistency:Option[ConsistencyLevel],
timestamp: Option[Long],
retryPolicy: Option[RetryPolicy],
fetchSize: Option[Int])
fetchSize: Option[Int],
requestTimeOut: Option[Int])
/**
* Singleton object to store constants
@ -71,7 +75,7 @@ object InterpreterLogic {
val fallThroughRetryPolicy = FallthroughRetryPolicy.INSTANCE
val loggingDefaultRetryPolicy = new LoggingRetryPolicy(defaultRetryPolicy)
val loggingDownGradingRetryPolicy = new LoggingRetryPolicy(downgradingConsistencyRetryPolicy)
val loggingFallThrougRetryPolicy = new LoggingRetryPolicy(fallThroughRetryPolicy)
val loggingFallThroughRetryPolicy = new LoggingRetryPolicy(fallThroughRetryPolicy)
val preparedStatements : mutable.Map[String,PreparedStatement] = new ConcurrentHashMap[String,PreparedStatement]().asScala
@ -273,7 +277,13 @@ class InterpreterLogic(val session: Session) {
.flatMap(x => Option(x.value))
.headOption
CassandraQueryOptions(consistency,serialConsistency, timestamp, retryPolicy, fetchSize)
val requestTimeOut: Option[Int] = parameters
.filter(_.paramType == RequestTimeOutParam)
.map(_.getParam[RequestTimeOut])
.flatMap(x => Option(x.value))
.headOption
CassandraQueryOptions(consistency,serialConsistency, timestamp, retryPolicy, fetchSize, requestTimeOut)
}
def generateSimpleStatement(st: SimpleStm, options: CassandraQueryOptions,context: InterpreterContext): SimpleStatement = {
@ -305,19 +315,38 @@ class InterpreterLogic(val session: Session) {
def maybeExtractVariables(statement: String, context: InterpreterContext): String = {
def findInAngularRepository(variable: String): Option[AnyRef] = {
val registry = context.getAngularObjectRegistry
val noteId = context.getNoteId
val paragraphId = context.getParagraphId
val paragraphScoped: Option[AnyRef] = Option(registry.get(variable, noteId, paragraphId)).map[AnyRef](_.get())
paragraphScoped
}
def extractVariableAndDefaultValue(statement: String, exp: String):String = {
exp match {
case MULTIPLE_CHOICES_VARIABLE_DEFINITION_PATTERN(variable,choices) => {
case MULTIPLE_CHOICES_VARIABLE_DEFINITION_PATTERN(variable, choices) => {
val escapedExp: String = exp.replaceAll( """\{""", """\\{""").replaceAll( """\}""", """\\}""").replaceAll("""\|""","""\\|""")
val listChoices:List[String] = choices.trim.split(CHOICES_SEPARATOR).toList
val paramOptions= listChoices.map(choice => new ParamOption(choice, choice))
val selected = context.getGui.select(variable, listChoices.head, paramOptions.toArray)
statement.replaceAll(escapedExp,selected.toString)
findInAngularRepository(variable) match {
case Some(value) => statement.replaceAll(escapedExp,value.toString)
case None => {
val listChoices:List[String] = choices.trim.split(CHOICES_SEPARATOR).toList
val paramOptions= listChoices.map(choice => new ParamOption(choice, choice))
val selected = context.getGui.select(variable, listChoices.head, paramOptions.toArray)
statement.replaceAll(escapedExp,selected.toString)
}
}
}
case SIMPLE_VARIABLE_DEFINITION_PATTERN(variable,defaultVal) => {
val escapedExp: String = exp.replaceAll( """\{""", """\\{""").replaceAll( """\}""", """\\}""")
val value = context.getGui.input(variable,defaultVal)
statement.replaceAll(escapedExp,value.toString)
findInAngularRepository(variable) match {
case Some(value) => statement.replaceAll(escapedExp,value.toString)
case None => {
val value = context.getGui.input(variable,defaultVal)
statement.replaceAll(escapedExp,value.toString)
}
}
}
case _ => throw new ParsingException(s"Invalid bound variable definition for '$exp' in '$statement'. It should be of form 'variable=defaultValue' or 'variable=value1|value2|...|valueN'")
}
@ -336,10 +365,11 @@ class InterpreterLogic(val session: Session) {
case FallThroughRetryPolicy => statement.setRetryPolicy(fallThroughRetryPolicy)
case LoggingDefaultRetryPolicy => statement.setRetryPolicy(loggingDefaultRetryPolicy)
case LoggingDowngradingRetryPolicy => statement.setRetryPolicy(loggingDownGradingRetryPolicy)
case LoggingFallThroughRetryPolicy => statement.setRetryPolicy(loggingFallThrougRetryPolicy)
case LoggingFallThroughRetryPolicy => statement.setRetryPolicy(loggingFallThroughRetryPolicy)
case _ => throw new InterpreterException(s"""Unknown retry policy ${options.retryPolicy.getOrElse("???")}""")
}
options.fetchSize.foreach(statement.setFetchSize(_))
options.requestTimeOut.foreach(statement.setReadTimeoutMillis(_))
}
private def createBoundStatement(codecRegistry: CodecRegistry, name: String, ps: PreparedStatement, rawBoundValues: String): BoundStatement = {

View file

@ -207,6 +207,16 @@ class JavaDriverConfig {
DEFAULT_MAX_REQUEST_PER_CONNECTION_LOCAL = "1024"
DEFAULT_MAX_REQUEST_PER_CONNECTION_REMOTE = "256"
return ProtocolVersion.V3
case "4" =>
DEFAULT_MAX_CONNECTION_PER_HOST_LOCAL = "1"
DEFAULT_MAX_CONNECTION_PER_HOST_REMOTE = "1"
DEFAULT_CORE_CONNECTION_PER_HOST_LOCAL = "1"
DEFAULT_CORE_CONNECTION_PER_HOST_REMOTE = "1"
DEFAULT_NEW_CONNECTION_THRESHOLD_LOCAL = "800"
DEFAULT_NEW_CONNECTION_THRESHOLD_REMOTE = "200"
DEFAULT_MAX_REQUEST_PER_CONNECTION_LOCAL = "1024"
DEFAULT_MAX_REQUEST_PER_CONNECTION_REMOTE = "256"
return ProtocolVersion.V4
case _ =>
DEFAULT_MAX_CONNECTION_PER_HOST_LOCAL = "1"
DEFAULT_MAX_CONNECTION_PER_HOST_REMOTE = "1"

View file

@ -44,6 +44,7 @@ object ParagraphParser {
LOGGING_DEFAULT_RETRY, LOGGING_DOWNGRADING_RETRY, LOGGING_FALLTHROUGH_RETRY)
.mkString("""^\s*@retryPolicy\s*=\s*(""", "|" , """)\s*$""").r
val FETCHSIZE_PATTERN = """^\s*@fetchSize\s*=\s*([0-9]+)\s*$""".r
val REQUEST_TIMEOUT_PATTERN = """^\s*@requestTimeOut\s*=\s*([0-9]+)\s*$""".r
val SIMPLE_STATEMENT_PATTERN = """([^;]+;)""".r
val PREPARE_STATEMENT_PATTERN = """^\s*@prepare\[([^]]+)\]\s*=\s*([^;]+)$""".r
@ -69,7 +70,7 @@ object ParagraphParser {
val UDF_PATTERN = """(?is)\s*(CREATE(?:\s+OR REPLACE)?\s+FUNCTION(?:\s+IF\s+NOT\s+EXISTS)?.+?(?:\s+|\n|\r|\f)AS(?:\s+|\n|\r|\f)(?:'|\$\$).+?(?:'|\$\$)\s*;)""".r
val GENERIC_STATEMENT_PREFIX =
"""(?is)\s*(?:INSERT|UPDATE|DELETE|SELECT|CREATE|UPDATE|
"""(?is)\s*(?:INSERT|UPDATE|DELETE|SELECT|CREATE|ALTER|
|DROP|GRANT|REVOKE|TRUNCATE|LIST|USE)\s+""".r
val VALID_IDENTIFIER = "[a-z][a-z0-9_]*"
@ -146,6 +147,7 @@ class ParagraphParser extends RegexParsers{
def timestamp: Parser[Timestamp] = """\s*@timestamp.+""".r ^^ {case x => extractTimestamp(x.trim)}
def retryPolicy: Parser[RetryPolicy] = """\s*@retryPolicy.+""".r ^^ {case x => extractRetryPolicy(x.trim)}
def fetchSize: Parser[FetchSize] = """\s*@fetchSize.+""".r ^^ {case x => extractFetchSize(x.trim)}
def requestTimeOut: Parser[RequestTimeOut] = """\s*@requestTimeOut.+""".r ^^ {case x => extractRequestTimeOut(x.trim)}
//Statements
def createFunctionStatement: Parser[SimpleStm] = UDF_PATTERN ^^{case x => extractUdfStatement(x.trim)}
@ -188,7 +190,7 @@ class ParagraphParser extends RegexParsers{
case begin ~ cqls ~ end => BatchStm(extractBatchType(begin),cqls)}
def queries:Parser[List[AnyBlock]] = rep(singleLineComment | multiLineComment | consistency | serialConsistency |
timestamp | retryPolicy | fetchSize | removePrepare | prepare | bind | batch | describeCluster |
timestamp | retryPolicy | fetchSize | requestTimeOut | removePrepare | prepare | bind | batch | describeCluster |
describeKeyspace | describeKeyspaces |
describeTable | describeTables |
describeType | describeTypes |
@ -244,6 +246,14 @@ class ParagraphParser extends RegexParsers{
}
}
def extractRequestTimeOut(text: String): RequestTimeOut = {
text match {
case REQUEST_TIMEOUT_PATTERN(requestTimeOut) => RequestTimeOut(requestTimeOut.trim.toInt)
case _ => throw new InterpreterException(s"Invalid syntax for @requestTimeOut. " +
s"It should comply to the pattern ${REQUEST_TIMEOUT_PATTERN.toString}")
}
}
def extractSimpleStatement(text: String): SimpleStm = {
text match {
case SIMPLE_STATEMENT_PATTERN(statement) => SimpleStm(statement)

View file

@ -44,6 +44,7 @@ object TextBlockHierarchy {
object TimestampParam extends ParameterType
object RetryPolicyParam extends ParameterType
object FetchSizeParam extends ParameterType
object RequestTimeOutParam extends ParameterType
abstract class QueryParameters(val paramType: ParameterType) extends AnyBlock(ParameterBlock) {
@ -60,6 +61,8 @@ object TextBlockHierarchy {
case class FetchSize(value: Int) extends QueryParameters(FetchSizeParam)
case class RequestTimeOut(value: Int) extends QueryParameters(RequestTimeOutParam)
abstract class RetryPolicy extends QueryParameters(RetryPolicyParam)
object DefaultRetryPolicy extends RetryPolicy

View file

@ -35,6 +35,7 @@ import com.datastax.driver.core.Session;
import info.archinnov.achilles.embedded.CassandraEmbeddedServerBuilder;
import org.apache.zeppelin.display.AngularObjectRegistry;
import org.apache.zeppelin.interpreter.Interpreter;
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterResult;
@ -45,7 +46,6 @@ import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -63,7 +63,7 @@ public class CassandraInterpreterTest {
.withScript("prepare_data.cql")
.withProtocolVersion(ProtocolVersion.V3)
.buildNativeSessionOnly();
// public static Session session = null;
private static CassandraInterpreter interpreter;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@ -73,7 +73,7 @@ public class CassandraInterpreterTest {
public static void setUp() {
Properties properties = new Properties();
final Cluster cluster = session.getCluster();
// final Cluster cluster = null;
properties.setProperty(CASSANDRA_CLUSTER_NAME, cluster.getClusterName());
properties.setProperty(CASSANDRA_COMPRESSION_PROTOCOL, "NONE");
properties.setProperty(CASSANDRA_CREDENTIALS_USERNAME, "none");
@ -289,6 +289,19 @@ public class CassandraInterpreterTest {
assertThat(actual.code()).isEqualTo(Code.SUCCESS);
}
@Test
public void should_execute_statement_with_request_timeout() throws Exception {
//Given
String statement = "@requestTimeOut=10000000\n" +
"SELECT * FROM zeppelin.artists;";
//When
final InterpreterResult actual = interpreter.interpret(statement, intrContext);
//Then
assertThat(actual.code()).isEqualTo(Code.SUCCESS);
}
@Test
public void should_execute_prepared_and_bound_statements() throws Exception {
//Given
@ -354,6 +367,8 @@ public class CassandraInterpreterTest {
@Test
public void should_extract_variable_from_statement() throws Exception {
//Given
AngularObjectRegistry angularObjectRegistry = new AngularObjectRegistry("cassandra", null);
when(intrContext.getAngularObjectRegistry()).thenReturn(angularObjectRegistry);
when(intrContext.getGui().input("login", "hsue")).thenReturn("hsue");
when(intrContext.getGui().input("age", "27")).thenReturn("27");

View file

@ -31,6 +31,8 @@ import com.datastax.driver.core.ConsistencyLevel;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.SimpleStatement;
import com.datastax.driver.core.Statement;
import org.apache.zeppelin.display.AngularObjectRegistry;
import org.apache.zeppelin.display.GUI;
import org.apache.zeppelin.display.Input.ParamOption;
import org.apache.zeppelin.interpreter.InterpreterContext;
@ -101,6 +103,8 @@ public class InterpreterLogicTest {
@Test
public void should_extract_variable_and_default_value() throws Exception {
//Given
AngularObjectRegistry angularObjectRegistry = new AngularObjectRegistry("cassandra", null);
when(intrContext.getAngularObjectRegistry()).thenReturn(angularObjectRegistry);
when(intrContext.getGui().input("table", "zeppelin.demo")).thenReturn("zeppelin.demo");
when(intrContext.getGui().input("id", "'John'")).thenReturn("'John'");
@ -114,6 +118,8 @@ public class InterpreterLogicTest {
@Test
public void should_extract_variable_and_choices() throws Exception {
//Given
AngularObjectRegistry angularObjectRegistry = new AngularObjectRegistry("cassandra", null);
when(intrContext.getAngularObjectRegistry()).thenReturn(angularObjectRegistry);
when(intrContext.getGui().select(eq("name"), eq("'Paul'"), optionsCaptor.capture())).thenReturn("'Jack'");
//When
@ -141,6 +147,23 @@ public class InterpreterLogicTest {
assertThat(actual).isEqualTo("SELECT * FROM zeppelin.demo");
}
@Test
public void should_extract_variable_from_angular_object_registry() throws Exception {
//Given
AngularObjectRegistry angularObjectRegistry = new AngularObjectRegistry("cassandra", null);
angularObjectRegistry.add("id", "from_angular_registry", "noteId", "paragraphId");
when(intrContext.getAngularObjectRegistry()).thenReturn(angularObjectRegistry);
when(intrContext.getNoteId()).thenReturn("noteId");
when(intrContext.getParagraphId()).thenReturn("paragraphId");
//When
final String actual = helper.maybeExtractVariables("SELECT * FROM zeppelin.demo WHERE id='{{id=John}}'", intrContext);
//Then
assertThat(actual).isEqualTo("SELECT * FROM zeppelin.demo WHERE id='from_angular_registry'");
verify(intrContext, never()).getGui();
}
@Test
public void should_error_if_incorrect_variable_definition() throws Exception {
//Given
@ -203,6 +226,18 @@ public class InterpreterLogicTest {
assertThat(actual.retryPolicy().get()).isSameAs(DowngradingRetryPolicy$.MODULE$);
}
@Test
public void should_extract_request_timeout_option() throws Exception {
//Given
List<QueryParameters> options = Arrays.<QueryParameters>asList(new RequestTimeOut(100));
//When
final CassandraQueryOptions actual = helper.extractQueryOptions(toScalaList(options));
//Then
assertThat(actual.requestTimeOut().get()).isEqualTo(100);
}
@Test
public void should_generate_simple_statement() throws Exception {
//Given
@ -211,6 +246,7 @@ public class InterpreterLogicTest {
Option.<ConsistencyLevel>empty(),
Option.empty(),
Option.<RetryPolicy>empty(),
Option.empty(),
Option.empty());
//When
@ -232,6 +268,7 @@ public class InterpreterLogicTest {
Option.<ConsistencyLevel>empty(),
Option.empty(),
Option.<RetryPolicy>empty(),
Option.empty(),
Option.empty());
//When

File diff suppressed because one or more lines are too long

View file

@ -182,6 +182,12 @@ class ParagraphParserTest extends FlatSpec
parsed should matchPattern { case parser.Success(FetchSize(100), _) =>}
}
"Parser" should "parse request timeout" in {
val query:String ="@requestTimeOut=100"
val parsed = parser.parseAll(parser.requestTimeOut, query)
parsed should matchPattern { case parser.Success(RequestTimeOut(100), _) =>}
}
"Parser" should "fails parsing invalid fetch size" in {
val query:String =""" @fetchSize=TEST""".stripMargin
val ex = intercept[InterpreterException] {
@ -944,4 +950,15 @@ class ParagraphParserTest extends FlatSpec
case parser.Success(List(SimpleStm(query)), _) =>
}
}
"Parser" should "parse ALTER KEYSPACE" in {
val query = "ALTER KEYSPACE toto WITH replication = " +
"{'class': 'SimpleStrategy', 'replication_factor': 1};"
val parsed = parser.parseAll(parser.queries, query)
parsed should matchPattern {
case parser.Success(List(SimpleStm(query)), _) =>
}
}
}

35
conf/interpreter-list Normal file
View file

@ -0,0 +1,35 @@
# 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.
#
#
# [name] [maven artifact] [description]
alluxio org.apache.zeppelin:zeppelin-alluxio:0.6.0 Alluxio interpreter
angular org.apache.zeppelin:zeppelin-angular:0.6.0 HTML and AngularJS view rendering
cassandra org.apache.zeppelin:zeppelin-cassandra:0.6.0 Cassandra interpreter
elasticsearch org.apache.zeppelin:zeppelin-elasticsearch:0.6.0 Elasticsearch interpreter
file org.apache.zeppelin:zeppelin-file:0.6.0 HDFS file interpreter
flink org.apache.zeppelin:zeppelin-flink:0.6.0 Flink interpreter
hbase org.apache.zeppelin:zeppelin-hbase:0.6.0 Hbase interpreter
ignite org.apache.zeppelin:zeppelin-ignite:0.6.0 Ignite interpreter
jdbc org.apache.zeppelin:zeppelin-jdbc:0.6.0 Jdbc interpreter
kylin org.apache.zeppelin:zeppelin-kylin:0.6.0 Kylin interpreter
lens org.apache.zeppelin:zeppelin-lens:0.6.0 Lens interpreter
livy org.apache.zeppelin:zeppelin-livy:0.6.0 Livy interpreter
md org.apache.zeppelin:zeppelin-markdown:0.6.0 Markdown support
postgresql org.apache.zeppelin:zeppelin-postgresql:0.6.0 Postgresql interpreter
python org.apache.zeppelin:zeppelin-python:0.6.0 Python interpreter
shell org.apache.zeppelin:zeppelin-shell:0.6.0 Shell command

View file

@ -18,27 +18,57 @@
[users]
# List of users with their password allowed to access Zeppelin.
# To use a different strategy (LDAP / Database / ...) check the shiro doc at http://shiro.apache.org/configuration.html#Configuration-INISections
admin = password1
admin = password1, admin
user1 = password2, role1, role2
user2 = password3, role3
user3 = password4, role2
# Sample LDAP configuration, for user Authentication, currently tested for single Realm
[main]
#ldapRealm = org.apache.shiro.realm.ldap.JndiLdapRealm
#ldapRealm.userDnTemplate = cn={0},cn=engg,ou=testdomain,dc=testdomain,dc=com
#ldapRealm.contextFactory.url = ldap://ldaphost:389
### A sample for configuring Active Directory Realm
#activeDirectoryRealm = org.apache.zeppelin.server.ActiveDirectoryGroupRealm
#activeDirectoryRealm.systemUsername = userNameA
#activeDirectoryRealm.systemPassword = passwordA
#activeDirectoryRealm.searchBase = CN=Users,DC=SOME_GROUP,DC=COMPANY,DC=COM
#activeDirectoryRealm.url = ldap://ldap.test.com:389
#activeDirectoryRealm.groupRolesMap = "CN=admin,OU=groups,DC=SOME_GROUP,DC=COMPANY,DC=COM":"admin","CN=finance,OU=groups,DC=SOME_GROUP,DC=COMPANY,DC=COM":"finance","CN=hr,OU=groups,DC=SOME_GROUP,DC=COMPANY,DC=COM":"hr"
#activeDirectoryRealm.authorizationCachingEnabled = false
### A sample for configuring LDAP Directory Realm
#ldapRealm = org.apache.zeppelin.server.LdapGroupRealm
## search base for ldap groups (only relevant for LdapGroupRealm):
#ldapRealm.contextFactory.environment[ldap.searchBase] = dc=COMPANY,dc=COM
#ldapRealm.contextFactory.url = ldap://ldap.test.com:389
#ldapRealm.userDnTemplate = uid={0},ou=Users,dc=COMPANY,dc=COM
#ldapRealm.contextFactory.authenticationMechanism = SIMPLE
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
### If caching of user is required then uncomment below lines
#cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
#securityManager.cacheManager = $cacheManager
securityManager.sessionManager = $sessionManager
# 86,400,000 milliseconds = 24 hour
securityManager.sessionManager.globalSessionTimeout = 86400000
shiro.loginUrl = /api/login
[roles]
role1 = *
role2 = *
role3 = *
admin = *
[urls]
# This section is used for url-based security.
# You can secure interpreter, configuration and credential information by urls. Comment or uncomment the below urls that you want to hide.
# anon means the access is anonymous.
# authcBasic means Basic Auth Security
# authc means Form based Auth Security
# To enfore security, comment the line below and uncomment the next one
/api/version = anon
#/api/interpreter/** = authc, roles[admin]
#/api/configurations/** = authc, roles[admin]
#/api/credential/** = authc, roles[admin]
/** = anon
#/** = authc

View file

@ -55,12 +55,13 @@ REM set HADOOP_CONF_DIR REM yarn-site.xml is located in configuration
REM Pyspark (supported with Spark 1.2.1 and above)
REM To configure pyspark, you need to set spark distribution's path to 'spark.home' property in Interpreter setting screen in Zeppelin GUI
REM set PYSPARK_PYTHON REM path to the python command. must be the same path on the driver(Zeppelin) and all workers.
REM set PYTHONPATH
REM set PYTHONPATH
REM Spark interpreter options
REM
REM set ZEPPELIN_SPARK_USEHIVECONTEXT REM Use HiveContext instead of SQLContext if set true. true by default.
REM set ZEPPELIN_SPARK_CONCURRENTSQL REM Execute multiple SQL concurrently if set true. false by default.
REM set ZEPPELIN_SPARK_IMPORTIMPLICIT REM Import implicits, UDF collection, and sql if set true. true by default.
REM set ZEPPELIN_SPARK_MAXRESULT REM Max number of SparkSQL result to display. 1000 by default.
REM ZeppelinHub connection configuration

View file

@ -55,15 +55,17 @@
# Pyspark (supported with Spark 1.2.1 and above)
# To configure pyspark, you need to set spark distribution's path to 'spark.home' property in Interpreter setting screen in Zeppelin GUI
# export PYSPARK_PYTHON # path to the python command. must be the same path on the driver(Zeppelin) and all workers.
# export PYTHONPATH
# export PYTHONPATH
## Spark interpreter options ##
##
# export ZEPPELIN_SPARK_USEHIVECONTEXT # Use HiveContext instead of SQLContext if set true. true by default.
# export ZEPPELIN_SPARK_CONCURRENTSQL # Execute multiple SQL concurrently if set true. false by default.
# export ZEPPELIN_SPARK_IMPORTIMPLICIT # Import implicits, UDF collection, and sql if set true. true by default.
# export ZEPPELIN_SPARK_MAXRESULT # Max number of SparkSQL result to display. 1000 by default.
# export ZEPPELIN_WEBSOCKET_MAX_TEXT_MESSAGE_SIZE # Size in characters of the maximum text message to be received by websocket. Defaults to 1024000
#### HBase interpreter configuration ####
## To connect to HBase running on a cluster, either HBASE_HOME or HBASE_CONF_DIR must be set
@ -75,4 +77,3 @@
# 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.

View file

@ -178,10 +178,16 @@
<property>
<name>zeppelin.interpreters</name>
<value>org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.hive.HiveInterpreter,org.apache.zeppelin.tajo.TajoInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.postgresql.PostgreSqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.phoenix.PhoenixInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter</value>
<value>org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,,org.apache.zeppelin.python.PythonInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.postgresql.PostgreSqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter</value>
<description>Comma separated interpreter configurations. First interpreter become a default</description>
</property>
<property>
<name>zeppelin.interpreter.group.order</name>
<value>"spark,md,angular,sh,livy,alluxio,file,psql,flink,python,ignite,lens,cassandra,geode,kylin,elasticsearch,scalding,jdbc,hbase</value>
<description></description>
</property>
<property>
<name>zeppelin.interpreter.connect.timeout</name>
<value>30000</value>

61
dev/common_release.sh Normal file
View file

@ -0,0 +1,61 @@
#!/bin/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.
#
# common fucntions
if [[ -z "${TAR}" ]]; then
TAR="/usr/bin/tar"
fi
if [[ -z "${SHASUM}" ]]; then
SHASUM="/usr/bin/shasum"
fi
if [[ -z "${WORKING_DIR}" ]]; then
WORKING_DIR="/tmp/zeppelin-release"
fi
mkdir "${WORKING_DIR}"
usage() {
echo "usage) $0 [Release version] [Branch or Tag]"
echo " ex. $0 0.6.0 v0.6.0"
exit 1
}
function git_clone() {
echo "Clone the source"
# clone source
git clone https://git-wip-us.apache.org/repos/asf/zeppelin.git "${WORKING_DIR}/zeppelin"
if [[ $? -ne 0 ]]; then
echo "Can not clone source repository"
exit 1
fi
cd "${WORKING_DIR}/zeppelin"
git checkout "${GIT_TAG}"
echo "Checked out ${GIT_TAG}"
# remove unnecessary files
rm "${WORKING_DIR}/zeppelin/.gitignore"
rm -rf "${WORKING_DIR}/zeppelin/.git"
rm -rf "${WORKING_DIR}/zeppelin/.github"
rm -rf "${WORKING_DIR}/zeppelin/docs"
}

View file

@ -18,116 +18,94 @@
#
# The script helps making a release.
# You need specify a release name and branch|tag name.
# You need to specify release version and branch|tag name.
#
# Here's some helpful documents for the release
# Here are some helpful documents for the release.
# http://www.apache.org/dev/release.html
# http://www.apache.org/dev/release-publishing
# http://incubator.apache.org/guides/releasemanagement.html
# http://incubator.apache.org/guides/release.html
# http://www.apache.org/dev/release-signing.html
# http://www.apache.org/dev/publishing-maven-artifacts.html
if [[ -z "${TAR}" ]]; then
TAR=/usr/bin/tar
fi
BASEDIR="$(dirname "$0")"
. "${BASEDIR}/common_release.sh"
echo "${BASEDIR}/common_release.sh"
if [[ -z "${SHASUM}" ]]; then
SHASUM="/usr/bin/shasum -a 512"
fi
if [[ -z "${WORKING_DIR}" ]]; then
WORKING_DIR=/tmp/incubator-zeppelin-release
if [[ $# -ne 2 ]]; then
usage
fi
if [[ -z "${GPG_PASSPHRASE}" ]]; then
echo "You need GPG_PASSPHRASE variable set"
exit 1
echo "You need GPG_PASSPHRASE variable set"
exit 1
fi
RELEASE_VERSION="$1"
GIT_TAG="$2"
if [[ $# -ne 2 ]]; then
echo "usage) $0 [Release name] [Branch or Tag]"
echo " ex. $0 0.5.0-incubating branch-0.5"
exit 1
fi
function make_source_package() {
# create source package
cd ${WORKING_DIR}
cp -r "zeppelin" "zeppelin-${RELEASE_VERSION}"
${TAR} cvzf "zeppelin-${RELEASE_VERSION}.tgz" "zeppelin-${RELEASE_VERSION}"
RELEASE_NAME="${1}"
BRANCH="${2}"
if [[ -d "${WORKING_DIR}" ]]; then
echo "Dir ${WORKING_DIR} already exists"
exit 1
fi
mkdir ${WORKING_DIR}
echo "Cloning the source and packaging"
# clone source
git clone -b ${BRANCH} git@github.com:apache/incubator-zeppelin.git ${WORKING_DIR}/zeppelin
if [[ $? -ne 0 ]]; then
echo "Can not clone source repository"
exit 1
fi
# remove unnecessary files
rm ${WORKING_DIR}/zeppelin/.gitignore
rm -rf ${WORKING_DIR}/zeppelin/.git
# create source package
cd ${WORKING_DIR}
cp -r zeppelin zeppelin-${RELEASE_NAME}
${TAR} cvzf zeppelin-${RELEASE_NAME}.tgz zeppelin-${RELEASE_NAME}
echo "Signing the source package"
cd ${WORKING_DIR}
echo $GPG_PASSPHRASE | gpg --passphrase-fd 0 --armor --output zeppelin-${RELEASE_NAME}.tgz.asc --detach-sig ${WORKING_DIR}/zeppelin-${RELEASE_NAME}.tgz
echo $GPG_PASSPHRASE | gpg --passphrase-fd 0 --print-md MD5 zeppelin-${RELEASE_NAME}.tgz > ${WORKING_DIR}/zeppelin-${RELEASE_NAME}.tgz.md5
${SHASUM} zeppelin-${RELEASE_NAME}.tgz > ${WORKING_DIR}/zeppelin-${RELEASE_NAME}.tgz.sha512
function make_binary_release() {
BIN_RELEASE_NAME="${1}"
BUILD_FLAGS="${2}"
cp -r ${WORKING_DIR}/zeppelin ${WORKING_DIR}/zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}
cd ${WORKING_DIR}/zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}
echo "mvn clean package -Pbuild-distr -DskipTests ${BUILD_FLAGS}"
mvn clean package -Pbuild-distr -DskipTests ${BUILD_FLAGS}
if [[ $? -ne 0 ]]; then
echo "Build failed. ${BUILD_FLAGS}"
exit 1
fi
# re-create package with proper dir name with binary license
cd zeppelin-distribution/target/zeppelin-*
mv zeppelin-* zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}
cat ../../src/bin_license/LICENSE >> zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}/LICENSE
cat ../../src/bin_license/NOTICE >> zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}/NOTICE
cp ../../src/bin_license/licenses/* zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}/licenses/
${TAR} cvzf zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}
# sign bin package
echo $GPG_PASSPHRASE | gpg --passphrase-fd 0 --armor --output zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz.asc --detach-sig zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz
echo $GPG_PASSPHRASE | gpg --passphrase-fd 0 --print-md MD5 zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz > zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz.md5
${SHASUM} zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz > zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz.sha512
mv zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz ${WORKING_DIR}/
mv zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz.asc ${WORKING_DIR}/
mv zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz.md5 ${WORKING_DIR}/
mv zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}.tgz.sha512 ${WORKING_DIR}/
# clean up build dir
rm -rf ${WORKING_DIR}/zeppelin-${RELEASE_NAME}-bin-${BIN_RELEASE_NAME}
echo "Signing the source package"
cd "${WORKING_DIR}"
echo "${GPG_PASSPHRASE}" | gpg --passphrase-fd 0 --armor \
--output "zeppelin-${RELEASE_VERSION}.tgz.asc" \
--detach-sig "${WORKING_DIR}/zeppelin-${RELEASE_VERSION}.tgz"
echo "${GPG_PASSPHRASE}" | gpg --passphrase-fd 0 \
--print-md MD5 "zeppelin-${RELEASE_VERSION}.tgz" > \
"${WORKING_DIR}/zeppelin-${RELEASE_VERSION}.tgz.md5"
echo "${GPG_PASSPHRASE}" | gpg --passphrase-fd 0 \
--print-md SHA512 "zeppelin-${RELEASE_VERSION}.tgz" > \
"${WORKING_DIR}/zeppelin-${RELEASE_VERSION}.tgz.sha512"
}
make_binary_release all "-Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark"
function make_binary_release() {
BIN_RELEASE_NAME="$1"
BUILD_FLAGS="$2"
cp -r "${WORKING_DIR}/zeppelin" "${WORKING_DIR}/zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}"
cd "${WORKING_DIR}/zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}"
echo "mvn clean package -Pbuild-distr -DskipTests ${BUILD_FLAGS}"
mvn clean package -Pbuild-distr -DskipTests ${BUILD_FLAGS}
if [[ $? -ne 0 ]]; then
echo "Build failed. ${BUILD_FLAGS}"
exit 1
fi
# re-create package with proper dir name with binary license
cd zeppelin-distribution/target/zeppelin-*
mv zeppelin-* "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}"
cat ../../src/bin_license/LICENSE >> "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}/LICENSE"
cat ../../src/bin_license/NOTICE >> "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}/NOTICE"
cp ../../src/bin_license/licenses/* "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}/licenses/"
${TAR} cvzf "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz" "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}"
# sign bin package
echo "${GPG_PASSPHRASE}" | gpg --passphrase-fd 0 --armor \
--output "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.asc" \
--detach-sig "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz"
echo "${GPG_PASSPHRASE}" | gpg --passphrase-fd 0 --print-md MD5 \
"zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz" > \
"zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.md5"
${SHASUM} -a 512 "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz" > \
"zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.sha512"
mv "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz" "${WORKING_DIR}/"
mv "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.asc" "${WORKING_DIR}/"
mv "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.md5" "${WORKING_DIR}/"
mv "zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}.tgz.sha512" "${WORKING_DIR}/"
# clean up build dir
rm -rf "${WORKING_DIR}/zeppelin-${RELEASE_VERSION}-bin-${BIN_RELEASE_NAME}"
}
git_clone
make_source_package
make_binary_release all "-Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pr"
make_binary_release netinst "-Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pr -pl !alluxio,!angular,!cassandra,!elasticsearch,!file,!flink,!hbase,!ignite,!jdbc,!kylin,!lens,!livy,!markdown,!postgresql,!python,!shell"
# remove non release files and dirs
rm -rf ${WORKING_DIR}/zeppelin
rm -rf ${WORKING_DIR}/zeppelin-${RELEASE_NAME}
rm -rf "${WORKING_DIR}/zeppelin"
rm -rf "${WORKING_DIR}/zeppelin-${RELEASE_VERSION}"
echo "Release files are created under ${WORKING_DIR}"

View file

@ -48,8 +48,8 @@ JIRA_USERNAME = os.environ.get("JIRA_USERNAME", "moon")
# ASF JIRA password
JIRA_PASSWORD = os.environ.get("JIRA_PASSWORD", "00000")
GITHUB_BASE = "https://github.com/apache/incubator-zeppelin/pull"
GITHUB_API_BASE = "https://api.github.com/repos/apache/incubator-zeppelin"
GITHUB_BASE = "https://github.com/apache/zeppelin/pull"
GITHUB_API_BASE = "https://api.github.com/repos/apache/zeppelin"
JIRA_BASE = "https://issues.apache.org/jira/browse"
JIRA_API_BASE = "https://issues.apache.org/jira"
# Prefix added to temporary branches
@ -280,7 +280,7 @@ def resolve_jira_issue(merge_branches, comment, default_jira_id=""):
def resolve_jira_issues(title, merge_branches, comment):
jira_ids = re.findall("ZEPPELIN-[0-9]{4,5}", title)
jira_ids = re.findall("ZEPPELIN-[0-9]{3,5}", title)
if len(jira_ids) == 0:
resolve_jira_issue(merge_branches, comment)

143
dev/publish_release.sh Executable file
View file

@ -0,0 +1,143 @@
#!/bin/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.
#
# The script helps publishing release to maven.
# You need to specify release version and branch|tag name.
#
# Here's some helpful documents for the release.
# http://www.apache.org/dev/publishing-maven-artifacts.html
BASEDIR="$(dirname "$0")"
. "${BASEDIR}/common_release.sh"
if [[ $# -ne 2 ]]; then
usage
fi
for var in GPG_PASSPHRASE ASF_USERID ASF_PASSWORD; do
if [[ -z "${!var}" ]]; then
echo "You need ${var} variable set"
exit 1
fi
done
export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=512m"
RED='\033[0;31m'
NC='\033[0m' # No Color
RELEASE_VERSION="$1"
GIT_TAG="$2"
PUBLISH_PROFILES="-Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pr"
PROJECT_OPTIONS="-pl !zeppelin-distribution"
NEXUS_STAGING="https://repository.apache.org/service/local/staging"
NEXUS_PROFILE="153446d1ac37c4"
function cleanup() {
echo "Remove working directory and maven local repository"
rm -rf ${WORKING_DIR}
rm -rf ${tmp_repo}
}
function curl_error() {
ret=${1}
if [[ $ret -ne 0 ]]; then
echo "curl response code is: ($ret)"
echo "See https://curl.haxx.se/libcurl/c/libcurl-errors.html to know the detailed cause of error."
echo -e "${RED}Failed to publish maven artifact to staging repository."
echo -e "IMPORTANT: You will have to re-run publish_release.sh to complete maven artifact publish.${NC}"
cleanup
exit 1
fi
}
function publish_to_maven() {
cd "${WORKING_DIR}/zeppelin"
# Force release version
mvn versions:set -DnewVersion="${RELEASE_VERSION}"
# Using Nexus API documented here:
# https://support.sonatype.com/hc/en-us/articles/213465868-Uploading-to-a-Staging-Repository-via-REST-API
echo "Creating Nexus staging repository"
repo_request="<promoteRequest><data><description>Apache Zeppelin ${RELEASE_VERSION}</description></data></promoteRequest>"
out="$(curl -X POST -d "${repo_request}" -u "${ASF_USERID}:${ASF_PASSWORD}" \
-H 'Content-Type:application/xml' -v \
"${NEXUS_STAGING}/profiles/${NEXUS_PROFILE}/start")"
create_ret=$?
curl_error $create_ret
staged_repo_id="$(echo ${out} | sed -e 's/.*\(orgapachezeppelin-[0-9]\{4\}\).*/\1/')"
if [[ -z "${staged_repo_id}" ]]; then
echo "Fail to create staging repository"
exit 1
fi
echo "Created Nexus staging repository: ${staged_repo_id}"
tmp_repo="$(mktemp -d /tmp/zeppelin-repo-XXXXX)"
echo "mvn clean install -Ppublish-distr \
-Dmaven.repo.local=${tmp_repo} \
${PUBLISH_PROFILES} ${PROJECT_OPTIONS}"
mvn clean install -Ppublish-distr -Dmaven.repo.local="${tmp_repo}" \
${PUBLISH_PROFILES} ${PROJECT_OPTIONS}
if [[ $? -ne 0 ]]; then
echo "Build failed."
exit 1
fi
pushd "${tmp_repo}/org/apache/zeppelin"
find . -type f | grep -v '\.jar$' | grep -v '\.pom$' |grep -v '\.war$' | xargs rm
echo "Creating hash and signature files"
for file in $(find . -type f); do
echo "${GPG_PASSPHRASE}" | gpg --passphrase-fd 0 --output "${file}.asc" \
--detach-sig --armor "${file}"
md5 -q "${file}" > "${file}.md5"
${SHASUM} -a 1 "${file}" | cut -f1 -d' ' > "${file}.sha1"
done
nexus_upload="${NEXUS_STAGING}/deployByRepositoryId/${staged_repo_id}"
echo "Uplading files to ${nexus_upload}"
for file in $(find . -type f); do
# strip leading ./
file_short="$(echo "${file}" | sed -e 's/\.\///')"
dest_url="${nexus_upload}/org/apache/zeppelin/$file_short"
echo " Uploading ${file_short}"
curl -u "${ASF_USERID}:${ASF_PASSWORD}" --upload-file "${file_short}" "${dest_url}"
upload_ret=$?
curl_error $upload_ret
done
echo "Closing nexus staging repository"
repo_request="<promoteRequest><data><stagedRepositoryId>${staged_repo_id}</stagedRepositoryId><description>Apache Zeppelin ${RELEASE_VERSION}</description></data></promoteRequest>"
out="$(curl -X POST -d "${repo_request}" -u "${ASF_USERID}:${ASF_PASSWORD}" \
-H 'Content-Type:application/xml' -v \
"${NEXUS_STAGING}/profiles/${NEXUS_PROFILE}/finish")"
close_ret=$?
curl_error $close_ret
echo "Closed Nexus staging repository: ${staged_repo_id}"
popd
echo "Complete publishing maven artifacts to apache staging repository"
echo "Once release candidate pass the vote, do not forget to hit the release button in https://repository.apache.org"
}
git_clone
publish_to_maven
cleanup

View file

@ -34,7 +34,7 @@ if len(sys.argv) == 1:
pr=sys.argv[1]
githubApi="https://api.github.com/repos/apache/incubator-zeppelin"
githubApi="https://api.github.com/repos/apache/zeppelin"
prInfo = json.load(urllib.urlopen(githubApi + "/pulls/" + pr))
if "message" in prInfo and prInfo["message"] == "Not Found":

View file

@ -31,9 +31,6 @@ See https://help.github.com/articles/using-jekyll-with-pages#installing-jekyll
## Bumping up version in a new release
* `ZEPPELIN_VERSION` and `BASE_PATH` property in _config.yml
* `Zeppelin <small>([VERSION])</small>` in _includes/themes/zeppelin/_navigation.html
should be updated
## Deploy to ASF svnpubsub infra (for committers only)
1. generate static website in `./_site`
@ -44,7 +41,7 @@ should be updated
2. checkout ASF repo
```
svn co https://svn.apache.org/repos/asf/incubator/zeppelin asf-zeppelin
svn co https://svn.apache.org/repos/asf/zeppelin asf-zeppelin
```
3. copy `zeppelin/docs/_site` to `asf-zeppelin/site/docs/[VERSION]`
4. ```svn commit```

View file

@ -12,16 +12,16 @@ encoding: utf-8
# Themes are encouraged to use these universal variables
# so be sure to set them if your theme uses them.
#
title : Apache Zeppelin (incubating)
title : Apache Zeppelin
tagline: Simplify bigdata analytics
author :
name : The Apache Software Foundation
email : dev@zeppelin.incubator.apache.org
email : dev@zeppelin.apache.org
github : apache
twitter : ASF
feedburner : feedname
ZEPPELIN_VERSION : 0.6.0-incubating-SNAPSHOT
ZEPPELIN_VERSION : 0.7.0-SNAPSHOT
# The production_url is only used when full-domain names are needed
# such as sitemap.txt
@ -31,7 +31,7 @@ ZEPPELIN_VERSION : 0.6.0-incubating-SNAPSHOT
# Else if you are pushing to username.github.io, replace with your username.
# Finally if you are pushing to a GitHub project page, include the project name at the end.
#
production_url : http://zeppelin.incubator.apache.org
production_url : http://zeppelin.apache.org
# All Jekyll-Bootstrap specific configurations are namespaced into this hash
#
JB :
@ -59,7 +59,7 @@ JB :
# - Only the following values are falsy: ["", null, false]
# - When setting BASE_PATH it must be a valid url.
# This means always setting the protocol (http|https) or prefixing with "/"
BASE_PATH : /docs/0.6.0-incubating-SNAPSHOT
BASE_PATH : /docs/0.7.0-SNAPSHOT
# By default, the asset_path is automatically defined relative to BASE_PATH plus the enabled theme.
# ex: [BASE_PATH]/assets/themes/[THEME-NAME]
@ -108,7 +108,7 @@ JB :
tracking_id : 'UA-45176241-2'
google_universal :
tracking_id : 'UA-45176241-5'
domain : 'zeppelin.incubator.apache.org'
domain : 'zeppelin.apache.org'
getclicky :
site_id :
mixpanel :

View file

@ -10,7 +10,7 @@
<a class="navbar-brand" href="{{BASE_PATH}}">
<img src="/assets/themes/zeppelin/img/zeppelin_logo.png" width="50" alt="I'm zeppelin">
<span style="vertical-align:middle">Zeppelin</span>
<span style="vertical-align:baseline"><small>(0.6.0-incubating-SNAPSHOT)</small></span>
<span style="vertical-align:baseline"><small>{{site.ZEPPELIN_VERSION}}</small></span>
</a>
</div>
<nav class="navbar-collapse collapse" role="navigation">
@ -18,31 +18,35 @@
<li>
<a href="#" data-toggle="dropdown" class="dropdown-toggle">Quick Start <b class="caret"></b></a>
<ul class="dropdown-menu">
<!-- li><span><b>Overview</b><span></li -->
<li><a href="{{BASE_PATH}}/index.html">Overview</a></li>
<li><a href="{{BASE_PATH}}/index.html">What is Apache Zeppelin ?</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>Install</b><span></li -->
<li class="title"><span><b>Getting Started</b><span></li>
<li><a href="{{BASE_PATH}}/install/install.html">Install</a></li>
<li><a href="{{BASE_PATH}}/install/yarn_install.html">YARN Install</a></li>
<li><a href="{{BASE_PATH}}/install/virtual_machine.html">Virtual Machine Install</a></li>
<li><a href="{{BASE_PATH}}/install/install.html#apache-zeppelin-configuration">Configuration</a></li>
<li><a href="{{BASE_PATH}}/quickstart/explorezeppelinui.html">Explore Zeppelin UI</a></li>
<li><a href="{{BASE_PATH}}/quickstart/tutorial.html">Tutorial</a></li>
<li role="separator" class="divider"></li>
<li><a href="{{BASE_PATH}}/install/upgrade.html">Upgrade Version</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>Tutorial</b><span></li -->
<li><a href="{{BASE_PATH}}/tutorial/tutorial.html">Tutorial</a></li>
<li role="separator" class="divider"></li>
<li><a href="{{BASE_PATH}}/ui_layout/zeppelin_layout.html">UI Layout</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>Guide</b><span></li -->
<li class="title"><span><b>Basic Feature Guide</b><span></li>
<li><a href="{{BASE_PATH}}/manual/dynamicform.html">Dynamic Form</a></li>
<li><a href="{{BASE_PATH}}/manual/publish.html">Publish your Paragraph</a></li>
<li><a href="{{BASE_PATH}}/manual/notebookashomepage.html">Customize Zeppelin Homepage</a></li>
<li role="separator" class="divider"></li>
<li class="title"><span><b>More</b><span></li>
<li><a href="{{BASE_PATH}}/install/virtual_machine.html">Zeppelin on Vagrant VM</a></li>
<li><a href="{{BASE_PATH}}/install/upgrade.html">Upgrade Zeppelin Version</a></li>
</ul>
</li>
<li>
<a href="#" data-toggle="dropdown" class="dropdown-toggle">Interpreter <b class="caret"></b></a>
<ul class="dropdown-menu">
<ul class="dropdown-menu scrollable-menu">
<li><a href="{{BASE_PATH}}/manual/interpreters.html">Overview</a></li>
<li role="separator" class="divider"></li>
<li class="title"><span><b>Usage</b><span></li>
<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 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>
<li><a href="{{BASE_PATH}}/interpreter/cassandra.html">Cassandra</a></li>
<li><a href="{{BASE_PATH}}/interpreter/elasticsearch.html">Elasticsearch</a></li>
@ -56,53 +60,51 @@
<li><a href="{{BASE_PATH}}/interpreter/lens.html">Lens</a></li>
<li><a href="{{BASE_PATH}}/interpreter/livy.html">Livy</a></li>
<li><a href="{{BASE_PATH}}/interpreter/markdown.html">Markdown</a></li>
<li><a href="{{BASE_PATH}}/interpreter/postgresql.html">Postgresql, hawq</a></li>
<li><a href="{{BASE_PATH}}/interpreter/python.html">Python</a></li>
<li><a href="{{BASE_PATH}}/interpreter/postgresql.html">Postgresql, HAWQ</a></li>
<li><a href="{{BASE_PATH}}/interpreter/r.html">R</a></li>
<li><a href="{{BASE_PATH}}/interpreter/scalding.html">Scalding</a></li>
<li><a href="{{BASE_PATH}}/pleasecontribute.html">Shell</a></li>
<li><a href="{{BASE_PATH}}/interpreter/shell.html">Shell</a></li>
<li><a href="{{BASE_PATH}}/interpreter/spark.html">Spark</a></li>
<li><a href="{{BASE_PATH}}/pleasecontribute.html">Tajo</a></li>
<li role="separator" class="divider"></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>
</ul>
</li>
<li>
<a href="#" data-toggle="dropdown" class="dropdown-toggle">Display System <b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="{{BASE_PATH}}/displaysystem/display.html">Text</a></li>
<li><a href="{{BASE_PATH}}/displaysystem/display.html#html">Html</a></li>
<li><a href="{{BASE_PATH}}/displaysystem/table.html">Table</a></li>
<li class="title"><span><b>Basic Display System</b><span></li>
<li><a href="{{BASE_PATH}}/displaysystem/basicdisplaysystem.html#text">Text</a></li>
<li><a href="{{BASE_PATH}}/displaysystem/basicdisplaysystem.html#html">Html</a></li>
<li><a href="{{BASE_PATH}}/displaysystem/basicdisplaysystem.html#table">Table</a></li>
<li role="separator" class="divider"></li>
<li class="title"><span><b>Angular API</b><span></li>
<li><a href="{{BASE_PATH}}/displaysystem/back-end-angular.html">Angular (backend API)</a></li>
<li><a href="{{BASE_PATH}}/displaysystem/front-end-angular.html">Angular (frontend API)</a></li>
</ul>
</li>
<li>
<a href="#" data-toggle="dropdown" class="dropdown-toggle">More <b class="caret"></b></a>
<ul class="dropdown-menu">
<!-- li><span><b>Manual</b><span></li -->
<li><a href="{{BASE_PATH}}/manual/notebookashomepage.html">Notebook as Homepage</a></li>
<a href="#" data-toggle="dropdown" class="dropdown-toggle">More<b class="caret"></b></a>
<ul class="dropdown-menu scrollable-menu" style="right: 0; left: auto;">
<li class="title"><span><b>Notebook Storage</b><span></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#notebook-storage-in-local-git-repository">Git Storage</a></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#notebook-storage-in-s3">S3 Storage</a></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#notebook-storage-in-azure">Azure Storage</a></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#storage-in-zeppelinhub">ZeppelinHub Storage</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>Notebook Storage</b><span></li -->
<li><a href="{{BASE_PATH}}/storage/storage.html#Git">Git Storage</a></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#S3">S3 Storage</a></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#Azure">Azure Storage</a></li>
<li><a href="{{BASE_PATH}}/storage/storage.html#ZeppelinHub">ZeppelinHub Storage</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>REST API</b><span></li -->
<li class="title"><span><b>REST API</b><span></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-interpreter.html">Interpreter API</a></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-notebook.html">Notebook API</a></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-configuration.html">Configuration API</a></li>
<li><a href="{{BASE_PATH}}/rest-api/rest-credential.html">Credential API</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>Security</b><span></li -->
<li><a href="{{BASE_PATH}}/security/overview.html">Security Overview</a></li>
<li class="title"><span><b>Security</b><span></li>
<li><a href="{{BASE_PATH}}/security/authentication.html">Authentication for NGINX</a></li>
<li><a href="{{BASE_PATH}}/security/shiroauthentication.html">Shiro Authentication</a></li>
<li><a href="{{BASE_PATH}}/security/notebook_authorization.html">Notebook Authorization</a></li>
<li><a href="{{BASE_PATH}}/security/interpreter_authorization.html">Interpreter Authorization</a></li>
<li><a href="{{BASE_PATH}}/security/datasource_authorization.html">Data Source Authorization</a></li>
<li role="separator" class="divider"></li>
<!-- li><span><b>Development</b><span></li -->
<li class="title"><span><b>Contibute</b><span></li>
<li><a href="{{BASE_PATH}}/development/writingzeppelininterpreter.html">Writing Zeppelin Interpreter</a></li>
<li><a href="{{BASE_PATH}}/development/writingzeppelinapplication.html">Writing Zeppelin Application (Experimental)</a></li>
<li><a href="{{BASE_PATH}}/development/howtocontribute.html">How to contribute (code)</a></li>
<li><a href="{{BASE_PATH}}/development/howtocontributewebsite.html">How to contribute (website)</a></li>
</ul>
@ -111,3 +113,4 @@
</nav><!--/.navbar-collapse -->
</div>
</div>

View file

@ -32,6 +32,8 @@
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="{{ ASSET_PATH }}/bootstrap/js/bootstrap.min.js"></script>
<script src="{{ ASSET_PATH }}/js/docs.js"></script>
<script src="{{ ASSET_PATH }}/js/anchor.min.js"></script>
<script src="{{ ASSET_PATH }}/js/toc.js"></script>
<!-- atom & rss feed -->
<link href="{{ BASE_PATH }}{{ site.JB.atom_path }}" type="application/atom+xml" rel="alternate" title="Sitewide ATOM Feed">
@ -42,7 +44,7 @@
{% include themes/zeppelin/_navigation.html %}
<div class="container">
<div class="content">
{{ content }}
<hr>
<footer>

View file

@ -1,13 +1,77 @@
/* Move down content because we have a fixed navbar that is 50px tall */
@import url(//fonts.googleapis.com/css?family=Patua+One);
@import url(//fonts.googleapis.com/css?family=Open+Sans);
body {
padding-top: 50px;
padding-bottom: 20px;
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
line-height: 1.6;
color: #4c555a;
letter-spacing: .2px;
}
.jumbotron {
background: #3071a9;
background-color: #3071a9;
}
.jumbotron h1,
.jumbotron p {
color: #fff;
}
.jumbotron p {
font-size: 19px;
}
.jumbotron .btn {
font-size: 16px;
}
.jumbotron .thumbnail {
margin-top: 0;
}
.jumbotron.small {
padding: 0 0 0 0;
color: #ffffff;
}
.jumbotron.small .title{
float: left;
font-weight: bold;
font-size: 20px;
height: 30px;
margin-right: 20px;
}
.jumbotron.small .subtitle{
font-size: 14px;
height: 30px;
vertical-align: text-bottom;
padding-top: 7px;
}
.jumbotron.small .description{
margin-top: 7px;
}
.jumbotron h1 {
font-family: 'Patua One', cursive;
.jumbotron h1 {
font-family: 'Patua One', cursive;
}
.jumbotron small {
font-size: 60%;
color: #FFF;
}
}
.jumbotron small {
font-size: 60%;
color: #FFF;
}
.navbar-brand {
@ -72,6 +136,33 @@ body {
background: #3071a9;
}
.scrollable-menu {
max-height: 500px;
overflow: auto;
}
.scrollable-menu::-webkit-scrollbar {
-webkit-appearance: none;
width: 7px;
}
.scrollable-menu::-webkit-scrollbar-thumb {
border-radius: 3px;
background-color: gray;
}
.index-header {
font-size: 16px;
font-style: italic;
margin-bottom: 15px;
margin-top: 15px;
}
.index-description {
line-height: 1.6;
padding: 10px;
}
@media (max-width: 768px) {
.navbar-collapse.in {
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.4);
@ -147,85 +238,11 @@ body {
}
}
.jumbotron h1,
.jumbotron p {
color: white;
}
.jumbotron .thumbnail {
margin-top: 0;
}
.jumbotron.small {
padding: 0 0 0 0;
color: white;
}
.jumbotron.small .title{
float: left;
font-weight: bold;
font-size: 20px;
height: 30px;
margin-right: 20px;
}
.jumbotron.small .subtitle{
font-size: 14px;
height: 30px;
vertical-align:text-bottom;
padding-top:7px;
}
.jumbotron.small .description{
margin-top: 7px;
}
/* screenshot img inside of doc */
.screenshot {
width: 800px;
}
/* Table on the index page */
.table-container {
position: absolute;
}
.table-stack {
width: 200px;
padding: 5px;
}
.table-stack table {
width: 100%;
}
.table-stack tr td{
border: 1px solid white;
height: 40px;
background: #6371a9;
color: white;
}
.table-stack .gray {
background:#DDDDDD;
color:#777777;
}
/* Table for property */
.table-configuration {
width : 100%;
border : 1px solid gray;
}
.table-configuration tr td {
border: 1px solid gray;
padding: 5px;
}
.table-configuration tr th {
border: 1px solid gray;
padding: 5px;
background: #B0C4DE;
}
.rotate270 {
width: 15px;
padding: 10px 0 0 0;
@ -237,132 +254,207 @@ body {
}
/* Custom container */
.content {
word-wrap: break-word;
}
.content :first-child {
margin-top: 0;
}
@media screen and (min-width: 64em) {
.content {
max-width: 64em;
padding: 2rem 6rem;
margin: 0 auto;
}
}
@media screen and (min-width: 42em) and (max-width: 64em) {
.content {
padding: 2rem 4rem;
}
}
@media screen and (max-width: 42em) {
.content {
padding: 2rem 1rem;
}
}
/* <a> */
.container a {
color: #4183C4; }
.content a {
color: #4183C4;
}
a.absent {
color: #cc0000; }
color: #cc0000;
}
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
/* <hn> */
.container h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative; }
.container h1 {
font-size: 30px;
color: black; }
.container h2 {
font-size: 28px;
padding-top: 5px;
padding-bottom: 5px;
border-bottom: 1px solid #E5E5E5;}
.container h3 {
font-size: 22px;
padding-top: 5px;
padding-bottom: 5px;
border-bottom: 1px solid #E5E5E5;}
.container h4 {
font-size: 18px; }
.container h5 {
font-size: 14px; }
.container h6 {
font-size: 14px;
color: #777777;}
/* <li, ul, ol> */
.container li {
margin: 0; }
.container li p.first {
display: inline-block;}
.container ul :first-child, ol :first-child {
margin-top: 0;
.content h1, h2, h3, h4, h5, h6 {
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
margin-top: 3rem;
margin-bottom: 1rem;
font-weight: bold;
color: rgba(21,21,21,0.8);
}
.content h1 {
font-size: 30px;
color: black;
}
.content h2 {
font-size: 28px;
padding-top: 5px;
padding-bottom: 5px;
border-bottom: 1px solid #E5E5E5;
}
.content h3 {
font-size: 22px;
padding-top: 5px;
padding-bottom: 5px;
}
.content h4 {
font-size: 18px;
}
.content h5 {
font-size: 14px;
}
.content h6 {
font-size: 14px;
color: #777777;
}
/* <table> */
.container table {
width : 100%;
padding: 0;
border-collapse: collapse; }
.container table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0; }
.container table tr th {
text-align: center;
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px; }
.container table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px;
.content img {
max-width: 100%;
}
/* <li, ul, ol> */
.content li {
margin: 0;
}
.content li p.first {
display: inline-block;
}
.content ul :first-child, ol :first-child {
margin-top: 0px;
}
.content .nav-tabs {
margin-bottom: 10px;
}
/* <code> */
.container code{
color:#000000;
font-size: 90%;
font-family: "Menlo", "Lucida Console", monospace;
background-color: #f8f8f8;
border: 1px solid #cccccc;
.content code {
padding: 2px 4px;
font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 90%;
color: #567482;
background-color: #f3f6fa;
border-radius: 0.3rem;
}
/* <pre> */
.container pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;}
.container pre code {
font-size: 95%;
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
.content pre {
padding: 0.8rem;
margin-top: 0;
margin-bottom: 1rem;
font: Consolas, "Liberation Mono", Menlo, Courier, monospace;
font-size: 90%;
color: #567482;
word-wrap: normal;
background-color: #f3f6fa;
border: solid 1px #dce6f0;
border-radius: 0.3rem;
}
.content pre > code {
padding: 0;
margin: 0;
font-size: 95%;
color: #567482;
word-break: normal;
white-space: pre;
background: transparent;
border: 0;
}
.content .highlight {
margin-bottom: 1rem;
}
.content .highlight pre {
margin-bottom: 0;
word-break: normal;
}
.content .highlight pre,
.content pre {
padding: 0.8rem;
overflow: auto;
font-size: 90%;
line-height: 1.45;
border-radius: 0.3rem;
-webkit-overflow-scrolling: touch;
}
.content pre code,
.content pre tt {
display: inline;
max-width: initial;
padding: 0;
margin: 0;
overflow: initial;
line-height: inherit;
word-wrap: normal;
background-color: transparent;
border: 0;
}
.content pre code:before, .main-content pre code:after,
.content pre tt:before,
.content pre tt:after {
content: normal;
}
/* <blockquote> */
.container blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777; }
.container blockquote > :first-child {
margin-top: 0; }
.container blockquote > :last-child {
margin-bottom: 0; }
.container blockquote p{
font-size: 14px;
/* <blockquotes> */
.content blockquote {
padding: 0 1rem;
margin-left: 0;
color: #819198;
border-left: 0.3rem solid #dce6f0;
}
.content blockquote > :first-child {
margin-top: 0;
}
.content blockquote > :last-child {
margin-bottom: 0;
}
.content blockquote p {
font-size: 14px;
}
/* <p>, <blockquote>, <table>, <pre>, <img> margin */
.container p, blockquote, table, pre, img {
margin: 12px 0;
/* <table> */
.content table {
display: block;
width: 100%;
overflow: auto;
word-break: normal;
word-break: keep-all;
-webkit-overflow-scrolling: touch;
font-size: 90%;
margin-top: 16px;
margin-bottom: 16px;
}
.container-narrow {
margin: 0 auto;
.content table th {
font-weight: bold;
text-align: center;
background-color: rgba(91, 138, 179, 0.10);
}
.container-narrow > hr {
margin: 30px 0;
.content table th,
.content table td {
padding: 0.5rem 1rem;
border: 1px solid #e9ebec;
}
/* posts index */
@ -432,32 +524,26 @@ a.anchor {
color: white;
}
.jumbotron h1 {
font-family: 'Patua One', cursive;
}
.jumbotron small {
font-size: 60%;
color: white;
}
.navbar-brand {
font-family: 'Patua One', cursive;
}
.navbar-brand small {
font-size: 14px;
font-family: 'Helvetica Neue', Helvetica;
font-family: 'Open Sans', 'Helvetica Neue', Helvetica;
color: white;
vertical-align: bottom;
}
.navbar-collapse.collapse {
max-height: 50px;
}
#apache .caret {
.navbar-inverse .navbar-nav a .caret,
.navbar-inverse .navbar-nav a:hover .caret {
margin-left: 4px;
border-top-color: white;
border-bottom-color: white;
}
.navbar-inverse .navbar-nav > .open > a,
@ -467,12 +553,27 @@ a.anchor {
background: #286090;
}
a.anchorjs-link:hover { text-decoration: none; }
/* Table of Contents(TOC) */
#toc {
padding-top: 12px;
padding-bottom: 12px;
}
#toc ul {
margin-left: -14px;
}
#toc ul ul {
margin-left: -18px;
}
/* Custom, iPhone Retina */
@media only screen and (max-width: 480px) {
.jumbotron h1 {
display: none;
}
.navbar-brand small {
display: none;
color: white;
@ -497,12 +598,17 @@ and (max-width: 1024px) {
}
}
/* docs dropdown menu */
/* master branch docs dropdown menu */
#menu .dropdown-menu li span {
padding: 3px 10px 10px 10px;
font-size: 13px;
}
#menu .title {
padding-bottom: 8px;
color: #3071a9;
}
#menu .caret {
border-top-color: white;
border-bottom-color: white;
@ -517,6 +623,25 @@ and (max-width: 1024px) {
margin-right: 50px;
}
.row img {
max-width: 100%;
/* gh-pages branch docs dropdown menu */
#docs .dropdown-menu {
left: 0;
right: auto;
}
#docs .dropdown-menu li span {
padding: 3px 10px 10px 10px;
font-size: 13px;
}
@media only screen and (max-width: 480px) {
#menu .title {
color: #bbb;
}
}
@media only screen and (max-width: 768px) {
#menu .title {
color: #bbb;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 119 KiB

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 696 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

After

Width:  |  Height:  |  Size: 331 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 328 KiB

After

Width:  |  Height:  |  Size: 352 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 KiB

After

Width:  |  Height:  |  Size: 330 KiB

View file

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View file

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View file

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View file

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View file

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View file

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View file

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 536 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

After

Width:  |  Height:  |  Size: 290 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Some files were not shown because too many files have changed in this diff Show more