Merge branch 'master' into ZEPPELIN-732-up

This commit is contained in:
Lee moon soo 2016-06-06 11:48:50 -07:00
commit 93fa766d7b
120 changed files with 2640 additions and 512 deletions

1
.gitignore vendored
View file

@ -26,6 +26,7 @@ conf/truststore
conf/interpreter.json
conf/notebook-authorization.json
conf/shiro.ini
conf/credentials.json
# other generated files
spark/dependency-reduced-pom.xml

View file

@ -219,9 +219,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/browse/ZEPPELIN-924?jql=project%20%3D%20ZEPPELIN%20and%20status%20%3D%20Open%20and%20labels%20in%20\(beginner%2C%20newbie\))
## 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/incubator-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/incubator-zeppelin-users/) ]
* [dev@zeppelin.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.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/incubator-zeppelin-dev/) ]
* [commits@zeppelin.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.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/incubator-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.

View file

@ -1,7 +1,7 @@
#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/>
**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/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/>
**Issue Tracker:** [Jira](https://issues.apache.org/jira/browse/ZEPPELIN)<br/>
@ -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

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.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.6.0-SNAPSHOT</version>
<name>Zeppelin: Alluxio interpreter</name>
<url>http://www.apache.org</url>

View file

@ -22,16 +22,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.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.6.0-SNAPSHOT</version>
<name>Zeppelin: Angular interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<dependencies>
<dependency>

View file

@ -22,17 +22,17 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.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>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Cassandra</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>

View file

@ -178,7 +178,7 @@
<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.hive.HiveInterpreter,org.apache.zeppelin.tajo.TajoInterpreter,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.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>
<description>Comma separated interpreter configurations. First interpreter become a default</description>
</property>

View file

@ -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)

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.6.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.6.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>(0.6.0-SNAPSHOT)</small></span>
</a>
</div>
<nav class="navbar-collapse collapse" role="navigation">
@ -56,6 +56,7 @@
<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/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>

View file

@ -8,7 +8,7 @@ group: development
# Contributing to Apache Zeppelin ( Code )
## IMPORTANT
Apache Zeppelin (incubating) is an [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) Software.
Apache Zeppelin is an [Apache2 License](http://www.apache.org/licenses/LICENSE-2.0.html) Software.
Any contributions to Zeppelin (Source code, Documents, Image, Website) means you agree with license all your contributions as Apache2 License.
## Setting up
@ -99,7 +99,10 @@ thrift -out zeppelin-interpreter/src/main/java/ --gen java zeppelin-interpreter/
## JIRA
Zeppelin manages its 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/browse/ZEPPELIN-924?jql=project%20%3D%20ZEPPELIN%20and%20status%20%3D%20Open%20and%20labels%20in%20\(beginner%2C%20newbie\)).
## Stay involved
Contributors should join the Zeppelin mailing lists.
* [dev@zeppelin.incubator.apache.org](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/) is for people who want to contribute code to Zeppelin. [subscribe](mailto:dev-subscribe@zeppelin.incubator.apache.org?subject=send this email to subscribe), [unsubscribe](mailto:dev-unsubscribe@zeppelin.incubator.apache.org?subject=send this email to unsubscribe), [archives](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/)
* [dev@zeppelin.apache.org](http://mail-archives.apache.org/mod_mbox/zeppelin-dev/) is for people who want to contribute code to Zeppelin. [subscribe](mailto:dev-subscribe@zeppelin.apache.org?subject=send this email to subscribe), [unsubscribe](mailto:dev-unsubscribe@zeppelin.apache.org?subject=send this email to unsubscribe), [archives](http://mail-archives.apache.org/mod_mbox/zeppelin-dev/)

View file

@ -52,4 +52,4 @@ Zeppelin manages its issues in Jira. [https://issues.apache.org/jira/browse/ZEPP
## Stay involved
Contributors should join the Zeppelin mailing lists.
* [dev@zeppelin.incubator.apache.org](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/) is for people who want to contribute code to Zeppelin. [subscribe](mailto:dev-subscribe@zeppelin.incubator.apache.org?subject=send this email to subscribe), [unsubscribe](mailto:dev-unsubscribe@zeppelin.incubator.apache.org?subject=send this email to unsubscribe), [archives](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/)
* [dev@zeppelin.apache.org](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/) is for people who want to contribute code to Zeppelin. [subscribe](mailto:dev-subscribe@zeppelin.apache.org?subject=send this email to subscribe), [unsubscribe](mailto:dev-unsubscribe@zeppelin.apache.org?subject=send this email to unsubscribe), [archives](http://mail-archives.apache.org/mod_mbox/incubator-zeppelin-dev/)

View file

@ -36,8 +36,44 @@ In 'Separate Interpreter for each note' mode, new Interpreter instance will be c
### Make your own Interpreter
Creating a new interpreter is quite simple. Just extend [org.apache.zeppelin.interpreter](https://github.com/apache/incubator-zeppelin/blob/master/zeppelin-interpreter/src/main/java/org/apache/zeppelin/interpreter/Interpreter.java) abstract class and implement some methods.
You can include `org.apache.zeppelin:zeppelin-interpreter:[VERSION]` artifact in your build system.
Your interpreter name is derived from the static register method.
You can include `org.apache.zeppelin:zeppelin-interpreter:[VERSION]` artifact in your build system. And you should your jars under your interpreter directory with specific directory name. Zeppelin server reads interpreter directories recursively and initializes interpreters including your own interpreter.
There are three locations where you can store your interpreter group, name and other information. Zeppelin server tries to find the location below. Next, Zeppelin tries to find `interpareter-setting.json` in your interpreter jar.
```
{ZEPPELIN_INTERPRETER_DIR}/{YOUR_OWN_INTERPRETER_DIR}/interpreter-setting.json
```
Here is an example of `interpareter-setting.json` on your own interpreter.
```json
[
{
"group": "your-group",
"name": "your-name",
"className": "your.own.interpreter.class",
"properties": {
"propertiies1": {
"envName": null,
"propertyName": "property.1.name",
"defaultValue": "propertyDefaultValue",
"description": "Property description"
},
"properties2": {
"envName": PROPERTIES_2,
"propertyName": null,
"defaultValue": "property2DefaultValue",
"description": "Property 2 description"
}, ...
}
},
{
...
}
]
```
Finally, Zeppelin uses static initialization with the following:
```
static {
@ -45,6 +81,8 @@ static {
}
```
**Static initialization is deprecated and will be supported until 0.6.0.**
The name will appear later in the interpreter name option box during the interpreter configuration process.
The name of the interpreter is what you later write to identify a paragraph which should be interpreted using this interpreter.

View file

@ -1,59 +0,0 @@
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl"?>
<rdf:RDF xml:lang="en"
xmlns="http://usefulinc.com/ns/doap#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:asfext="http://projects.apache.org/ns/asfext#"
xmlns:foaf="http://xmlns.com/foaf/0.1/">
<!--
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.
-->
<Project rdf:about="http://zeppelin.incubator.apache.org/">
<created>2015-09-12</created>
<license rdf:resource="http://spdx.org/licenses/Apache-2.0" />
<name>Apache Zeppelin (incubating)</name>
<homepage rdf:resource="http://zeppelin.incubator.apache.org/" />
<asfext:pmc rdf:resource="http://incubator.apache.org" />
<shortdesc>Zeppelin is a collaborative data analytics and visualization tool for distributed, general-purpose data processing systems</shortdesc>
<description>Zeppelin is a modern web-based tool for the data scientists to collaborate over large-scale data exploration and visualization projects. </description>
<bug-database rdf:resource="https://issues.apache.org/jira/browse/ZEPPELIN" />
<mailing-list rdf:resource="http://zeppelin.incubator.apache.org/community.html" />
<download-page rdf:resource="http://zeppelin.incubator.apache.org/download.html" />
<programming-language>Java</programming-language>
<programming-language>JavaScript</programming-language>
<programming-language>Scala</programming-language>
<category rdf:resource="http://projects.apache.org/category/big-data" />
<release>
<Version>
<name>0.5.0-incubating</name>
<created>2015-07-31</created>
<revision>0.5.0-incubating</revision>
</Version>
</release>
<repository>
<GitRepository>
<location rdf:resource="https://git-wip-us.apache.org/repos/asf/incubator-zeppelin.git"/>
<browse rdf:resource="https://git1-us-west.apache.org/repos/asf?p=incubator-zeppelin.git;a=summary"/>
</GitRepository>
</repository>
<maintainer>
<foaf:Person>
<foaf:name>Alexander Bezzubov</foaf:name>
<foaf:mbox rdf:resource="mailto:bzz@apache.org"/>
</foaf:Person>
</maintainer>
</Project>
</rdf:RDF>

View file

@ -116,11 +116,7 @@ If you want to learn more about this feature, please visit [this page](./manual/
<br />
### 100% Opensource
Apache Zeppelin (incubating) is Apache2 Licensed software. Please check out the [source repository](http://git.apache.org/incubator-zeppelin.git) and [How to contribute](./development/howtocontribute.html)
Apache Zeppelin is Apache2 Licensed software. Please check out the [source repository](http://git.apache.org/incubator-zeppelin.git) and [How to contribute](./development/howtocontribute.html)
Zeppelin has a very active development community.
Join the [Mailing list](./community.html) and report issues on our [Issue tracker](https://issues.apache.org/jira/browse/ZEPPELIN).
<br />
### Undergoing Incubation
Apache Zeppelin is an effort undergoing [incubation](https://incubator.apache.org/index.html) at The Apache Software Foundation (ASF), sponsored by the Incubator. 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.
Join the [Mailing list](https://zeppelin.apache.org/community.html) and report issues on our [Issue tracker](https://issues.apache.org/jira/browse/ZEPPELIN).

View file

@ -28,7 +28,7 @@ In this documentation, we will explain how you can install Zeppelin from **Binar
### Install with Binary Package
If you want to install Zeppelin with latest binary package, please visit [this page](http://zeppelin.incubator.apache.org/download.html).
If you want to install Zeppelin with latest binary package, please visit [this page](http://zeppelin.apache.org/download.html).
### Build from Zeppelin Source

View file

@ -75,7 +75,7 @@ This document assumes Spark 1.6.0 is installed at /usr/lib/spark.
#### Zeppelin
Checkout source code from [git://git.apache.org/incubator-zeppelin.git](https://github.com/apache/incubator-zeppelin.git) or download binary package from [Download page](https://zeppelin.incubator.apache.org/download.html).
Checkout source code from [git://git.apache.org/incubator-zeppelin.git](https://github.com/apache/incubator-zeppelin.git) or download binary package from [Download page](https://zeppelin.apache.org/download.html).
You can refer [Install](install.html) page for the details.
This document assumes that Zeppelin is located under `/home/zeppelin/incubator-zeppelin`.

View file

@ -74,7 +74,7 @@ After configuring Ignite interpreter, create your own notebook. Then you can bin
![Binding Interpreters](../assets/themes/zeppelin/img/docs-img/ignite-interpreter-binding.png)
For more interpreter binding information see [here](http://zeppelin.incubator.apache.org/docs/manual/interpreters.html).
For more interpreter binding information see [here](http://zeppelin.apache.org/docs/manual/interpreters.html).
### How to use Ignite SQL interpreter
In order to execute SQL query, use ` %ignite.ignitesql ` prefix. <br>

View file

@ -82,7 +82,7 @@ After configuring Lens interpreter, create your own notebook, then you can bind
![Zeppelin Notebook Interpreter Binding](../assets/themes/zeppelin/img/docs-img/lens-interpreter-binding.png)
For more interpreter binding information see [here](http://zeppelin.incubator.apache.org/docs/manual/interpreters.html).
For more interpreter binding information see [here](http://zeppelin.apache.org/docs/manual/interpreters.html).
### How to use
You can analyze your data by using [OLAP Cube](http://lens.apache.org/user/olap-cube.html) [QL](http://lens.apache.org/user/cli.html) which is a high level SQL like language to query and describe data sets organized in data cubes.

117
docs/interpreter/python.md Normal file
View file

@ -0,0 +1,117 @@
---
layout: page
title: "Python Interpreter"
description: "Python Interpreter"
group: manual
---
{% include JB/setup %}
## Python 2 & 3 Interpreter for Apache Zeppelin
## Configuration
<table class="table-configuration">
<tr>
<th>Property</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td>python</td>
<td>python</td>
<td>Path of the already installed Python binary (could be python2 or python3).
If python is not in your $PATH you can set the absolute directory (example : /usr/bin/python)
</td>
</tr>
</table>
## Enabling Python Interpreter
In a notebook, to enable the **Python** interpreter, click on the **Gear** icon and select **Python**
## Using the Python Interpreter
In a paragraph, use **_%python_** to select the **Python** interpreter and then input all commands.
The interpreter can only work if you already have python installed (the interpreter doesn't bring it own python binaries).
To access the help, type **help()**
## Python modules
The interpreter can use all modules already installed (with pip, easy_install...)
## Apply Zeppelin Dynamic Forms
You can leverage [Zeppelin Dynamic Form]({{BASE_PATH}}/manual/dynamicform.html) inside your Python code.
**Zeppelin Dynamic Form can only be used if py4j Python library is installed in your system. If not, you can install it with `pip install py4j`.**
Example :
```python
%python
### Input form
print (z.input("f1","defaultValue"))
### Select form
print (z.select("f1",[("o1","1"),("o2","2")],"2"))
### Checkbox form
print("".join(z.checkbox("f3", [("o1","1"), ("o2","2")],["1"])))
```
## Zeppelin features not fully supported by the Python Interpreter
* Interrupt a paragraph execution (`cancel()` method) is currently only supported in Linux and MacOs. If interpreter runs in another operating system (for instance MS Windows) , interrupt a paragraph will close the whole interpreter. A JIRA ticket ([ZEPPELIN-893](https://issues.apache.org/jira/browse/ZEPPELIN-893)) is opened to implement this feature in a next release of the interpreter.
* Progression bar in webUI (`getProgress()` method) is currently not implemented.
* Code-completion is currently not implemented.
## Matplotlib integration
The python interpreter can display matplotlib graph with the function **_zeppelin_show()_**
You need to already have matplotlib module installed and a running XServer to use this functionality !
```python
%python
import matplotlib.pyplot as plt
plt.figure()
(.. ..)
zeppelin_show(plt)
plt.close()
```
zeppelin_show function can take optional parameters to adapt graph width and height
```python
%python
zeppelin_show(plt,width='50px')
zeppelin_show(plt,height='150px')
```
[![pythonmatplotlib](../interpreter/screenshots/pythonMatplotlib.png)](/docs/interpreter/screenshots/pythonMatplotlib.png)
## Technical description - Interpreter architecture
### Dev prerequisites
* Python 2 and 3 installed with py4j (0.9.2) and matplotlib (1.31 or later) installed on each
* Tests only checks the interpreter logic and starts any Python process ! Python process is mocked with a class that simply output it input.
* Make sure the code wrote in bootstrap.py and bootstrap_input.py is Python2 and 3 compliant.
* Use PEP8 convention for python code.
### Technical overview
* When interpreter is starting it launches a python process inside a Java ProcessBuilder. Python is started with -i (interactive mode) and -u (unbuffered stdin, stdout and stderr) options. Thus the interpreter has a "sleeping" python process.
* Interpreter sends command to python with a Java `outputStreamWiter` and read from an `InputStreamReader`. To know when stop reading stdout, interpreter sends `print "*!?flush reader!?*"`after each command and reads stdout until he receives back the `*!?flush reader!?*`.
* When interpreter is starting, it sends some Python code (bootstrap.py and bootstrap_input.py) to initialize default behavior and functions (`help(), z.input()...`). bootstrap_input.py is sent only if py4j library is detected inside Python process.
* [Py4J](https://www.py4j.org/) python and java libraries is used to load Input zeppelin Java class into the python process (make java code with python code !). Therefore the interpreter can directly create Zeppelin input form inside the Python process (and eventually with some python variable already defined). JVM opens a random open port to be accessible from python process.
* JavaBuilder can't send SIGINT signal to interrupt paragraph execution. Therefore interpreter directly send a `kill SIGINT PID` to python process to interrupt execution. Python process catch SIGINT signal with some code defined in bootstrap.py
* Matplotlib display feature is made with SVG export (in string) and then displays it with html code.

View file

@ -8,7 +8,7 @@ group: manual
## R Interpreter
This is a the Apache (incubating) Zeppelin project, with the addition of support for the R programming language and R-spark integration.
This is a the Apache Zeppelin project, with the addition of support for the R programming language and R-spark integration.
### Requirements

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -143,7 +143,7 @@ for example,
* **yarn-client** in Yarn client mode
* **mesos://host:5050** in Mesos cluster
That's it. Zeppelin will work with any version of Spark and any deployment type without rebuilding Zeppelin in this way. ( Zeppelin 0.5.5-incubating release works up to Spark 1.5.2 )
That's it. Zeppelin will work with any version of Spark and any deployment type without rebuilding Zeppelin in this way. (Zeppelin 0.5.6-incubating release works up to Spark 1.6.1 )
> Note that without exporting `SPARK_HOME`, it's running in local mode with included version of Spark. The included version may vary depending on the build profile.
@ -204,7 +204,7 @@ Here are few examples:
spark.files /path/mylib1.py,/path/mylib2.egg,/path/mylib3.zip
### 3. Dynamic Dependency Loading via %dep interpreter
> Note: `%dep` interpreter is deprecated since v0.6.0-incubating.
> Note: `%dep` interpreter is deprecated since v0.6.0.
`%dep` interpreter load libraries to `%spark` and `%pyspark` but not to `%spark.sql` interpreter so we recommend you to use first option instead.
When your code requires external library, instead of doing download/copy/restart Zeppelin, you can easily do following jobs using `%dep` interpreter.

View file

@ -26,7 +26,7 @@ limitations under the License.
Note that Zeppelin REST API receive or return JSON objects, it it recommended you install some JSON viewers such as
[JSON View](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc).
If you work with zeppelin and find a need for an additional REST API, please [file an issue or send us mail](http://zeppelin.incubator.apache.org/community.html).
If you work with zeppelin and find a need for an additional REST API, please [file an issue or send us mail](http://zeppelin.apache.org/community.html).
<br />
## Interpreter REST API List

View file

@ -32,3 +32,5 @@ The interpret method takes the user string as parameter and executes the jdbc ca
In case of Presto, we don't need password if the Presto DB server runs backend code using HDFS authorization for the user.
For databases like Vertica and Mysql we have to store password information for users.
The Credentials tab in the navbar allows users to save credentials for data sources which are passed to interpreters.

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-elasticsearch</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Elasticsearch interpreter</name>
<url>http://www.apache.org</url>

View file

@ -22,13 +22,13 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-file</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: File System Interpreters</name>
<url>http://www.apache.org</url>

View file

@ -22,17 +22,17 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-flink</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Flink</name>
<description>Zeppelin flink support</description>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<flink.version>1.0.0</flink.version>

View file

@ -23,13 +23,13 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-geode</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Apache Geode interpreter</name>
<url>http://geode.incubator.apache.org/</url>

View file

@ -22,13 +22,13 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-hbase</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: HBase interpreter</name>
<url>http://www.apache.org</url>

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-hive</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Hive interpreter</name>
<url>http://www.apache.org</url>
<!--

View file

@ -22,18 +22,18 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<artifactId>zeppelin-ignite</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Apache Ignite interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<ignite.version>1.5.0.final</ignite.version>
<ignite.version>1.6.0</ignite.version>
<ignite.scala.binary.version>2.10</ignite.scala.binary.version>
<ignite.scala.version>2.10.4</ignite.scala.version>
</properties>

View file

@ -23,13 +23,13 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-jdbc</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: JDBC interpreter</name>
<url>http://www.apache.org</url>

View file

@ -23,16 +23,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-kylin</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Kylin interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<dependencies>
@ -127,4 +127,4 @@
</build>
</project>
</project>

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-lens</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Lens interpreter</name>
<url>http://www.apache.org</url>

View file

@ -24,16 +24,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-livy</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Livy interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<!--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.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-markdown</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Markdown interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<dependencies>
<dependency>

View file

@ -22,16 +22,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-phoenix</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Apache Phoenix Interpreter</name>
<description>Zeppelin interprter for Apache Phoenix</description>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<phoenix.version>4.4.0-HBase-1.0</phoenix.version>

27
pom.xml
View file

@ -35,10 +35,10 @@
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin</artifactId>
<packaging>pom</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin</name>
<description>Zeppelin project</description>
<url>http://zeppelin.incubator.apache.org/</url>
<url>http://zeppelin.apache.org/</url>
<parent>
<groupId>org.apache</groupId>
@ -60,27 +60,6 @@
<developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-zeppelin.git</developerConnection>
</scm>
<developers>
<developer>
<id>moon</id>
<name>Lee moon soo</name>
<organization>NFLabs</organization>
<organizationUrl>http://www.nflabs.com</organizationUrl>
</developer>
<developer>
<id>alex</id>
<name>Alexander Bezzubov</name>
<organization>NFLabs</organization>
<organizationUrl>http://www.nflabs.com</organizationUrl>
</developer>
<developer>
<id>anthonycorbacho</id>
<name>Anthony Corbacho</name>
<organization>NFLabs</organization>
<organizationUrl>http://www.nflabs.com</organizationUrl>
</developer>
</developers>
<inceptionYear>2013</inceptionYear>
<modules>
@ -103,6 +82,7 @@
<module>flink</module>
<module>ignite</module>
<module>kylin</module>
<module>python</module>
<module>lens</module>
<module>cassandra</module>
<module>elasticsearch</module>
@ -491,6 +471,7 @@
<exclude>**/zeppelin-distribution/src/bin_license/**</exclude>
<exclude>conf/interpreter.json</exclude>
<exclude>conf/notebook-authorization.json</exclude>
<exclude>conf/credentials.json</exclude>
<exclude>conf/zeppelin-env.sh</exclude>
<exclude>spark-*-bin*/**</exclude>
<exclude>.spark-dist/**</exclude>

View file

@ -5,5 +5,5 @@ This interpreter supports the following SQL engines:
* [Apache HAWQ](http://pivotal.io/big-data/pivotal-hawq) - Powerful [Open Source](https://wiki.apache.org/incubator/HAWQProposal) SQL-On-Hadoop engine.
* [Greenplum](http://pivotal.io/big-data/pivotal-greenplum-database) - MPP database built on open source PostgreSQL.
The official documentation: [PostgreSQL, HAWQ](https://zeppelin.incubator.apache.org/docs/interpreter/postgresql.html)
The official documentation: [PostgreSQL, HAWQ](https://zeppelin.apache.org/docs/interpreter/postgresql.html)

View file

@ -23,13 +23,13 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-postgresql</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: PostgreSQL interpreter</name>
<url>http://www.apache.org</url>

155
python/pom.xml Normal file
View file

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-python</artifactId>
<packaging>jar</packaging>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Python interpreter</name>
<url>http://zeppelin.apache.org</url>
<properties>
<py4j.version>0.9.2</py4j.version>
</properties>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>zeppelin-interpreter</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>net.sf.py4j</groupId>
<artifactId>py4j</artifactId>
<version>${py4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.0</version>
<scope>test</scope>
</dependency>
</dependencies>
<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>
<executions>
<execution>
<id>enforce</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/../../interpreter/python</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
</configuration>
</execution>
<execution>
<id>copy-artifact</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/../../interpreter/python</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>${project.packaging}</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,262 @@
/*
* 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.
*/
package org.apache.zeppelin.python;
import org.apache.zeppelin.display.GUI;
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.InterpreterResult.Code;
import org.apache.zeppelin.scheduler.Job;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import py4j.GatewayServer;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.util.Collection;
import java.util.List;
import java.util.Properties;
/**
* Python interpreter for Zeppelin.
*/
public class PythonInterpreter extends Interpreter {
Logger logger = LoggerFactory.getLogger(PythonInterpreter.class);
public static final String BOOTSTRAP_PY = "/bootstrap.py";
public static final String BOOTSTRAP_INPUT_PY = "/bootstrap_input.py";
public static final String ZEPPELIN_PYTHON = "zeppelin.python";
public static final String DEFAULT_ZEPPELIN_PYTHON = "python";
private Integer port;
private GatewayServer gatewayServer;
PythonProcess process = null;
private long pythonPid;
private Boolean py4J = false;
private InterpreterContext context;
static {
Interpreter.register(
"python",
"python",
PythonInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add(ZEPPELIN_PYTHON, DEFAULT_ZEPPELIN_PYTHON,
"Python directory. Default : python (assume python is in your $PATH)")
.build()
);
}
public PythonInterpreter(Properties property) {
super(property);
}
@Override
public void open() {
logger.info("Starting Python interpreter .....");
logger.info("Python path is set to:" + property.getProperty(ZEPPELIN_PYTHON));
process = getPythonProcess();
try {
process.open();
} catch (IOException e) {
logger.error("Can't start the python process", e);
}
try {
logger.info("python PID : " + process.getPid());
} catch (Exception e) {
logger.warn("Can't find python pid process", e);
}
try {
logger.info("Bootstrap interpreter with " + BOOTSTRAP_PY);
bootStrapInterpreter(BOOTSTRAP_PY);
} catch (IOException e) {
logger.error("Can't execute " + BOOTSTRAP_PY + " to initiate python process", e);
}
if (py4J = isPy4jInstalled()) {
port = findRandomOpenPortOnAllLocalInterfaces();
logger.info("Py4j gateway port : " + port);
try {
gatewayServer = new GatewayServer(this, port);
gatewayServer.start();
logger.info("Bootstrap inputs with " + BOOTSTRAP_INPUT_PY);
bootStrapInterpreter(BOOTSTRAP_INPUT_PY);
} catch (IOException e) {
logger.error("Can't execute " + BOOTSTRAP_INPUT_PY + " to " +
"initialize Zeppelin inputs in python process", e);
}
}
}
@Override
public void close() {
logger.info("closing Python interpreter .....");
try {
process.close();
gatewayServer.shutdown();
} catch (IOException e) {
logger.error("Can't close the interpreter", e);
}
}
@Override
public InterpreterResult interpret(String cmd, InterpreterContext contextInterpreter) {
this.context = contextInterpreter;
String output = sendCommandToPython(cmd);
return new InterpreterResult(Code.SUCCESS, output.replaceAll(">>>", "")
.replaceAll("\\.\\.\\.", "").trim());
}
@Override
public void cancel(InterpreterContext context) {
try {
process.interrupt();
} catch (IOException e) {
logger.error("Can't interrupt the python interpreter", e);
}
}
@Override
public FormType getFormType() {
return FormType.NATIVE;
}
@Override
public int getProgress(InterpreterContext context) {
return 0;
}
@Override
public Scheduler getScheduler() {
return SchedulerFactory.singleton().createOrGetParallelScheduler(
PythonInterpreter.class.getName() + this.hashCode(), 10);
}
@Override
public List<String> completion(String buf, int cursor) {
return null;
}
public PythonProcess getPythonProcess() {
if (process == null)
return new PythonProcess(getProperty(ZEPPELIN_PYTHON));
else
return process;
}
private Job getRunningJob(String paragraphId) {
Job foundJob = null;
Collection<Job> jobsRunning = getScheduler().getJobsRunning();
for (Job job : jobsRunning) {
if (job.getId().equals(paragraphId)) {
foundJob = job;
}
}
return foundJob;
}
private String sendCommandToPython(String cmd) {
String output = "";
logger.info("Sending : \n " + cmd);
try {
output = process.sendAndGetResult(cmd);
} catch (IOException e) {
logger.error("Error when sending commands to python process", e);
}
return output;
}
private void bootStrapInterpreter(String file) throws IOException {
BufferedReader bootstrapReader = new BufferedReader(
new InputStreamReader(
PythonInterpreter.class.getResourceAsStream(file)));
String line = null;
String bootstrapCode = "";
while ((line = bootstrapReader.readLine()) != null) {
bootstrapCode += line + "\n";
}
if (py4J && port != null && port != -1) {
bootstrapCode = bootstrapCode.replaceAll("\\%PORT\\%", port.toString());
}
logger.info("Bootstrap python interpreter with \n " + bootstrapCode);
sendCommandToPython(bootstrapCode);
}
public GUI getGui() {
return context.getGui();
}
public Integer getPy4JPort() {
return port;
}
public Boolean isPy4jInstalled() {
String output = sendCommandToPython("\n\nimport py4j\n");
if (output.contains("ImportError"))
return false;
else return true;
}
private int findRandomOpenPortOnAllLocalInterfaces() {
Integer port = -1;
try (ServerSocket socket = new ServerSocket(0);) {
port = socket.getLocalPort();
socket.close();
} catch (IOException e) {
logger.error("Can't find an open port", e);
}
return port;
}
}

View file

@ -0,0 +1,133 @@
/*
* 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.
*/
package org.apache.zeppelin.python;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
/**
* Object encapsulated interactive
* Python process (REPL) used by python interpreter
*/
public class PythonProcess {
Logger logger = LoggerFactory.getLogger(PythonProcess.class);
InputStream stdout;
OutputStream stdin;
BufferedWriter writer;
BufferedReader reader;
Process process;
private String binPath;
private long pid;
public PythonProcess(String binPath) {
this.binPath = binPath;
}
public void open() throws IOException {
ProcessBuilder builder = new ProcessBuilder(binPath, "-iu");
builder.redirectErrorStream(true);
process = builder.start();
stdout = process.getInputStream();
stdin = process.getOutputStream();
writer = new BufferedWriter(new OutputStreamWriter(stdin));
reader = new BufferedReader(new InputStreamReader(stdout));
try {
pid = findPid();
} catch (Exception e) {
logger.warn("Can't find python pid process", e);
pid = -1;
}
}
public void close() throws IOException {
process.destroy();
reader.close();
writer.close();
stdin.close();
stdout.close();
}
public void interrupt() throws IOException {
if (pid > -1) {
logger.info("Sending SIGINT signal to PID : " + pid);
Runtime.getRuntime().exec("kill -SIGINT " + pid);
} else {
logger.warn("Non UNIX/Linux system, close the interpreter");
close();
}
}
public String sendAndGetResult(String cmd) throws IOException {
writer.write(cmd + "\n\n");
writer.write("print (\"*!?flush reader!?*\")\n\n");
writer.flush();
String output = "";
String line;
while (!(line = reader.readLine()).contains("*!?flush reader!?*")) {
logger.debug("Readed line from python shell : " + line);
if (line.equals("...")) {
logger.warn("Syntax error ! ");
output += "Syntax error ! ";
break;
}
output += "\r" + line + "\n";
}
return output;
}
private long findPid() throws NoSuchFieldException, IllegalAccessException {
long pid = -1;
if (process.getClass().getName().equals("java.lang.UNIXProcess")) {
Field f = process.getClass().getDeclaredField("pid");
f.setAccessible(true);
pid = f.getLong(process);
f.setAccessible(false);
}
return pid;
}
public long getPid() {
return pid;
}
}

View file

@ -0,0 +1,108 @@
# 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.
# PYTHON 2 / 3 comptability :
# bootstrap.py must be runnable with Python 2 and 3
# Remove interactive mode displayhook
import sys
import signal
try:
import StringIO as io
except ImportError:
import io as io
sys.displayhook = lambda x: None
def intHandler(signum, frame): # Set the signal handler
print ("Paragraph interrupted")
raise KeyboardInterrupt()
signal.signal(signal.SIGINT, intHandler)
def help():
print ('%html')
print ('<h2>Python Interpreter help</h2>')
print ('<h3>Python 2 & 3 comptability</h3>')
print ('<p>The interpreter is compatible with Python 2 & 3.<br/>')
print ('To change Python version, ')
print ('change in the interpreter configuration the python to the ')
print ('desired version (example : python=/usr/bin/python3)</p>')
print ('<h3>Python modules</h3>')
print ('<p>The interpreter can use all modules already installed ')
print ('(with pip, easy_install, etc)</p>')
print ('<h3>Forms</h3>')
print ('You must install py4j in order to use '
'the form feature (pip install py4j)')
print ('<h4>Input form</h4>')
print ('<pre>print (z.input("f1","defaultValue"))</pre>')
print ('<h4>Selection form</h4>')
print ('<pre>print(z.select("f2", [("o1","1"), ("o2","2")],2))</pre>')
print ('<h4>Checkbox form</h4>')
print ('<pre> print("".join(z.checkbox("f3", [("o1","1"), '
'("o2","2")],["1"])))</pre>')
print ('<h3>Matplotlib graph</h3>')
print ('<div>The interpreter can display matplotlib graph with ')
print ('the function zeppelin_show()</div>')
print ('<div> You need to already have matplotlib module installed ')
print ('to use this functionality !</div><br/>')
print ('''<pre>import matplotlib.pyplot as plt
plt.figure()
(.. ..)
zeppelin_show(plt)
plt.close()
</pre>''')
print ('<div><br/> zeppelin_show function can take optional parameters ')
print ('to adapt graph width and height</div>')
print ("<div><b>example </b>:")
print('''<pre>zeppelin_show(plt,width='50px')
zeppelin_show(plt,height='150px') </pre></div>''')
# Matplotlib show function
def zeppelin_show(p, width="0", height="0"):
img = io.StringIO()
p.savefig(img, format='svg')
img.seek(0)
style = ""
if(width != "0"):
style += 'width:'+width
if(height != "0"):
if(len(style) != 0):
style += ","
style += 'height:'+height
print("%html <div style='" + style + "'>" + img.read() + "<div>")
# If py4j is detected, these class will be override
# with the implementation in bootstrap_input.py
class PyZeppelinContext():
errorMsg = "You must install py4j Python module " \
"(pip install py4j) to use Zeppelin dynamic forms features"
def __init__(self, zc):
self.z = zc
def input(self, name, defaultValue=""):
print (self.errorMsg)
def select(self, name, options, defaultValue=""):
print (self.errorMsg)
def checkbox(self, name, options, defaultChecked=[]):
print (self.errorMsg)
z = PyZeppelinContext("")

View file

@ -0,0 +1,51 @@
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from py4j.java_gateway import JavaGateway
from py4j.java_gateway import java_import, JavaGateway, GatewayClient
client = GatewayClient(port=%PORT%)
gateway = JavaGateway(client)
java_import(gateway.jvm, "org.apache.zeppelin.display.Input")
class PyZeppelinContext():
paramOption = gateway.jvm.org.apache.zeppelin.display.Input.ParamOption
javaList = gateway.jvm.java.util.ArrayList
def __init__(self, zc):
self.z = zc
def input(self, name, defaultValue=""):
return self.z.getGui().input(name, defaultValue)
def select(self, name, options, defaultValue=""):
javaOptions = gateway.new_array(self.paramOption, len(options))
i = 0
for tuple in options:
javaOptions[i] = self.paramOption(tuple[0], tuple[1])
i += 1
return self.z.getGui().select(name, defaultValue, javaOptions)
def checkbox(self, name, options, defaultChecked=[]):
javaOptions = gateway.new_array(self.paramOption, len(options))
i = 0
for tuple in options:
javaOptions[i] = self.paramOption(tuple[0], tuple[1])
i += 1
javaDefaultCheck = self.javaList()
for check in defaultChecked:
javaDefaultCheck.append(check)
return self.z.getGui().checkbox(name, javaDefaultCheck, javaOptions)
z = PyZeppelinContext(gateway.entry_point)

View file

@ -0,0 +1,233 @@
/*
* 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.
*/
package org.apache.zeppelin.python;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.anyString;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.junit.Before;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Properties;
/**
* Python interpreter unit test
*/
public class PythonInterpreterTest {
Logger logger = LoggerFactory.getLogger(PythonProcess.class);
public static final String ZEPPELIN_PYTHON = "zeppelin.python";
public static final String DEFAULT_ZEPPELIN_PYTHON = "python";
PythonInterpreter pythonInterpreter = null;
PythonProcess mockPythonProcess;
String cmdHistory;
@Before
public void beforeTest() {
cmdHistory = "";
/*Mock python process*/
mockPythonProcess = mock(PythonProcess.class);
when(mockPythonProcess.getPid()).thenReturn((long) 1);
try {
when(mockPythonProcess.sendAndGetResult(anyString())).thenAnswer(
new Answer<String>() {
@Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
return answerFromPythonMock(invocationOnMock);
}
});
} catch (IOException e) {
logger.error("Can't initiate python process", e);
}
Properties properties = new Properties();
properties.put(ZEPPELIN_PYTHON, DEFAULT_ZEPPELIN_PYTHON);
pythonInterpreter = spy(new PythonInterpreter(properties));
when(pythonInterpreter.getPythonProcess()).thenReturn(mockPythonProcess);
try {
when(mockPythonProcess.sendAndGetResult(eq("\n\nimport py4j\n"))).thenReturn("ImportError");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testOpenInterpreter() {
pythonInterpreter.open();
assertEquals(pythonInterpreter.getPythonProcess().getPid(), 1);
}
@Test
public void testPy4jIsNotInstalled() {
/*
If Py4J is not installed, bootstrap_input.py
is not sent to Python process and
py4j JavaGateway is not running
*/
pythonInterpreter.open();
assertNull(pythonInterpreter.getPy4JPort());
assertTrue(cmdHistory.contains("def help()"));
assertTrue(cmdHistory.contains("class PyZeppelinContext():"));
assertTrue(cmdHistory.contains("z = PyZeppelinContext"));
assertTrue(cmdHistory.contains("def zeppelin_show"));
assertFalse(cmdHistory.contains("GatewayClient"));
}
@Test
public void testPy4JInstalled() {
/*
If Py4J installed, bootstrap_input.py
is sent to interpreter and JavaGateway is
running
*/
try {
when(mockPythonProcess.sendAndGetResult(eq("\n\nimport py4j\n"))).thenReturn(">>>");
} catch (IOException e) {
e.printStackTrace();
}
pythonInterpreter.open();
Integer py4jPort = pythonInterpreter.getPy4JPort();
assertNotNull(py4jPort);
assertTrue(cmdHistory.contains("def help()"));
assertTrue(cmdHistory.contains("class PyZeppelinContext():"));
assertTrue(cmdHistory.contains("z = PyZeppelinContext"));
assertTrue(cmdHistory.contains("def zeppelin_show"));
assertTrue(cmdHistory.contains("GatewayClient(port=" + py4jPort + ")"));
assertTrue(cmdHistory.contains("org.apache.zeppelin.display.Input"));
assertTrue(checkSocketAdress(py4jPort));
}
@Test
public void testClose() {
try {
when(mockPythonProcess.sendAndGetResult(eq("\n\nimport py4j\n"))).thenReturn(">>>");
} catch (IOException e) {
e.printStackTrace();
}
pythonInterpreter.open();
Integer py4jPort = pythonInterpreter.getPy4JPort();
assertNotNull(py4jPort);
pythonInterpreter.close();
assertFalse(checkSocketAdress(py4jPort));
try {
verify(mockPythonProcess, times(1)).close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testInterpret() {
pythonInterpreter.open();
cmdHistory = "";
InterpreterResult result = pythonInterpreter.interpret("print a", null);
assertEquals(InterpreterResult.Code.SUCCESS, result.code());
assertEquals("%text print a", result.toString());
}
private boolean checkSocketAdress(Integer py4jPort) {
Socket s = new Socket();
SocketAddress sa = new InetSocketAddress("localhost", py4jPort);
Boolean working = null;
try {
s.connect(sa, 10000);
} catch (IOException e) {
working = false;
}
if (working == null) {
working = s.isConnected();
try {
s.close();
} catch (IOException e) {
logger.error("Can't close connection to localhost:" + py4jPort, e);
}
}
return working;
}
private String answerFromPythonMock(InvocationOnMock invocationOnMock) {
Object[] inputs = invocationOnMock.getArguments();
String cmdToExecute = (String) inputs[0];
if (cmdToExecute != null) {
cmdHistory += cmdToExecute;
String[] lines = cmdToExecute.split("\\n");
String output = "";
for (int i = 0; i < lines.length; i++) {
output += ">>>" + lines[i];
}
return output;
} else {
return ">>>";
}
}
}

View file

@ -23,7 +23,7 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
@ -40,14 +40,6 @@
<scala.binary.version>2.10</scala.binary.version>
</properties>
<developers>
<developer>
<id>amos</id>
<name>Amos Elberg</name>
</developer>
</developers>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>

View file

@ -22,16 +22,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-scalding</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Scalding interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<scala.version>2.10.4</scala.version>

View file

@ -22,16 +22,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-shell</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Shell interpreter</name>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<dependencies>
<dependency>

View file

@ -16,24 +16,24 @@
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-spark-dependencies</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Spark dependencies</name>
<description>Zeppelin spark support</description>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<spark.version>1.4.1</spark.version>
@ -43,7 +43,7 @@
<hadoop.version>2.3.0</hadoop.version>
<yarn.version>${hadoop.version}</yarn.version>
<avro.version>1.7.7</avro.version>
<avro.mapred.classifier></avro.mapred.classifier>
<avro.mapred.classifier/>
<jets3t.version>0.7.1</jets3t.version>
<protobuf.version>2.4.1</protobuf.version>
@ -54,7 +54,9 @@
<spark.download.url>
http://archive.apache.org/dist/spark/${spark.archive}/${spark.archive}.tgz
</spark.download.url>
<spark.bin.download.url>http://archive.apache.org/dist/spark/spark-${spark.version}/spark-${spark.version}-bin-without-hadoop.tgz</spark.bin.download.url>
<spark.bin.download.url>
http://archive.apache.org/dist/spark/spark-${spark.version}/spark-${spark.version}-bin-without-hadoop.tgz
</spark.bin.download.url>
<spark.dist.cache>${project.build.directory}/../../.spark-dist</spark.dist.cache>
<py4j.version>0.8.2.1</py4j.version>
</properties>
@ -249,7 +251,7 @@
<!-- Spark -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.10</artifactId>
<artifactId>spark-core_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
<exclusions>
<exclusion>
@ -261,31 +263,31 @@
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-repl_2.10</artifactId>
<artifactId>spark-repl_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.10</artifactId>
<artifactId>spark-sql_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-hive_2.10</artifactId>
<artifactId>spark-hive_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming_2.10</artifactId>
<artifactId>spark-streaming_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-streaming-twitter_2.10</artifactId>
<artifactId>spark-streaming-twitter_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
@ -438,7 +440,7 @@
</dependencies>
</profile>
<profile>
<profile>
<id>spark-1.4</id>
<properties>
<spark.version>1.4.1</spark.version>
@ -509,6 +511,9 @@
<profile>
<id>spark-1.6</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spark.version>1.6.1</spark.version>
<py4j.version>0.9</py4j.version>
@ -516,9 +521,6 @@
<akka.version>2.3.11</akka.version>
<protobuf.version>2.5.0</protobuf.version>
</properties>
<dependencies>
</dependencies>
</profile>
<profile>
@ -585,6 +587,16 @@
</properties>
</profile>
<profile>
<id>hadoop-2.7</id>
<properties>
<hadoop.version>2.7.2</hadoop.version>
<protobuf.version>2.5.0</protobuf.version>
<jets3t.version>0.9.0</jets3t.version>
<avro.mapred.classifier>hadoop2</avro.mapred.classifier>
</properties>
</profile>
<profile>
<id>mapr3</id>
<activation>
@ -596,12 +608,16 @@
<jets3t.version>0.7.1</jets3t.version>
</properties>
<repositories>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</profile>
@ -634,12 +650,16 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</profile>
@ -672,12 +692,16 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</profile>
@ -710,12 +734,16 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</profile>
@ -748,12 +776,16 @@
</dependency>
</dependencies>
<repositories>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots><enabled>false</enabled></snapshots>
<releases><enabled>true</enabled></releases>
</repository>
<repository>
<id>mapr-releases</id>
<url>http://repository.mapr.com/maven/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
</profile>
@ -763,7 +795,7 @@
<dependencies>
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-yarn_2.10</artifactId>
<artifactId>spark-yarn_${scala.binary.version}</artifactId>
<version>${spark.version}</version>
</dependency>
@ -845,7 +877,7 @@
<zip destfile="${project.build.directory}/../../interpreter/spark/pyspark/pyspark.zip"
basedir="${project.build.directory}/spark-dist/${spark.archive}/python"
includes="pyspark/*.py,pyspark/**/*.py"/>
</target>
</target>
</configuration>
</execution>
</executions>
@ -901,7 +933,9 @@
<outputDirectory>${project.build.directory}/../../interpreter/spark/R/lib</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/spark-bin-dist/spark-${spark.version}-bin-without-hadoop/R/lib</directory>
<directory>
${project.build.directory}/spark-bin-dist/spark-${spark.version}-bin-without-hadoop/R/lib
</directory>
</resource>
</resources>
</configuration>
@ -911,7 +945,7 @@
</plugins>
</build>
</profile>
</profiles>
<build>

View file

@ -22,17 +22,17 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-spark</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Spark</name>
<description>Zeppelin spark support</description>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<jsoup.version>1.8.2</jsoup.version>
@ -313,6 +313,7 @@
<exclude>**/metastore_db/</exclude>
<exclude>**/README.md</exclude>
<exclude>**/dependency-reduced-pom.xml</exclude>
<exclude>**/interpreter-setting.json</exclude>
</excludes>
</configuration>
</plugin>

View file

@ -62,23 +62,6 @@ import scala.tools.nsc.settings.MutableSettings.PathSetting;
*
*/
public class DepInterpreter extends Interpreter {
static {
Interpreter.register(
"dep",
"spark",
DepInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add("zeppelin.dep.localrepo",
getSystemDefault("ZEPPELIN_DEP_LOCALREPO", null, "local-repo"),
"local repository for dependency loader")
.add("zeppelin.dep.additionalRemoteRepository",
"spark-packages,http://dl.bintray.com/spark-packages/maven,false;",
"A list of 'id,remote-repository-URL,is-snapshot;' for each remote repository.")
.build());
}
private SparkIMain intp;
private ByteArrayOutputStream out;
private SparkDependencyContext depc;

View file

@ -77,17 +77,6 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
private String scriptPath;
boolean pythonscriptRunning = false;
static {
Interpreter.register(
"pyspark",
"spark",
PySparkInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add("zeppelin.pyspark.python",
SparkInterpreter.getSystemDefault("PYSPARK_PYTHON", null, "python"),
"Python command to run pyspark with").build());
}
public PySparkInterpreter(Properties property) {
super(property);

View file

@ -72,6 +72,7 @@ import scala.reflect.io.AbstractFile;
import scala.tools.nsc.Settings;
import scala.tools.nsc.interpreter.Completion.Candidates;
import scala.tools.nsc.interpreter.Completion.ScalaCompleter;
import scala.tools.nsc.settings.MutableSettings;
import scala.tools.nsc.settings.MutableSettings.BooleanSetting;
import scala.tools.nsc.settings.MutableSettings.PathSetting;
@ -82,38 +83,6 @@ import scala.tools.nsc.settings.MutableSettings.PathSetting;
public class SparkInterpreter extends Interpreter {
public static Logger logger = LoggerFactory.getLogger(SparkInterpreter.class);
static {
Interpreter.register(
"spark",
"spark",
SparkInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add("spark.app.name",
getSystemDefault("SPARK_APP_NAME", "spark.app.name", "Zeppelin"),
"The name of spark application.")
.add("master",
getSystemDefault("MASTER", "spark.master", "local[*]"),
"Spark master uri. ex) spark://masterhost:7077")
.add("spark.executor.memory",
getSystemDefault(null, "spark.executor.memory", ""),
"Executor memory per worker instance. ex) 512m, 32g")
.add("spark.cores.max",
getSystemDefault(null, "spark.cores.max", ""),
"Total number of cores to use. Empty value uses all available core.")
.add("zeppelin.spark.useHiveContext",
getSystemDefault("ZEPPELIN_SPARK_USEHIVECONTEXT",
"zeppelin.spark.useHiveContext", "true"),
"Use HiveContext instead of SQLContext if it is true.")
.add("zeppelin.spark.maxResult",
getSystemDefault("ZEPPELIN_SPARK_MAXRESULT", "zeppelin.spark.maxResult", "1000"),
"Max number of SparkSQL result to display.")
.add("args", "", "spark commandline args")
.add("zeppelin.spark.printREPLOutput", "true",
"Print REPL output")
.build()
);
}
private ZeppelinContext z;
private SparkILoop interpreter;
private SparkIMain intp;
@ -496,6 +465,12 @@ public class SparkInterpreter extends Interpreter {
System.setProperty("scala.repl.name.line", "line" + this.hashCode() + "$");
// To prevent 'File name too long' error on some file system.
MutableSettings.IntSetting numClassFileSetting = settings.maxClassfileName();
numClassFileSetting.v_$eq(128);
settings.scala$tools$nsc$settings$ScalaSettings$_setter_$maxClassfileName_$eq(
numClassFileSetting);
synchronized (sharedInterpreterLock) {
/* create scala repl */
if (printREPLOutput()) {

View file

@ -42,32 +42,6 @@ public class SparkRInterpreter extends Interpreter {
private static String renderOptions;
private ZeppelinR zeppelinR;
static {
Interpreter.register(
"r",
"spark",
SparkRInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add("zeppelin.R.cmd",
SparkInterpreter.getSystemDefault("ZEPPELIN_R_CMD", "zeppelin.R.cmd", "R"),
"R repl path")
.add("zeppelin.R.knitr",
SparkInterpreter.getSystemDefault("ZEPPELIN_R_KNITR", "zeppelin.R.knitr", "true"),
"whether use knitr or not")
.add("zeppelin.R.image.width",
SparkInterpreter.getSystemDefault("ZEPPELIN_R_IMAGE_WIDTH",
"zeppelin.R.image.width", "100%"),
"")
.add("zeppelin.R.render.options",
SparkInterpreter.getSystemDefault("ZEPPELIN_R_RENDER_OPTIONS",
"zeppelin.R.render.options",
"out.format = 'html', comment = NA, "
+ "echo = FALSE, results = 'asis', message = F, warning = F"),
"")
.build());
}
public SparkRInterpreter(Properties property) {
super(property);
}

View file

@ -46,27 +46,6 @@ public class SparkSqlInterpreter extends Interpreter {
Logger logger = LoggerFactory.getLogger(SparkSqlInterpreter.class);
AtomicInteger num = new AtomicInteger(0);
static {
Interpreter.register(
"sql",
"spark",
SparkSqlInterpreter.class.getName(),
new InterpreterPropertyBuilder()
.add("zeppelin.spark.maxResult",
SparkInterpreter.getSystemDefault("ZEPPELIN_SPARK_MAXRESULT",
"zeppelin.spark.maxResult", "1000"),
"Max number of SparkSQL result to display.")
.add("zeppelin.spark.concurrentSQL",
SparkInterpreter.getSystemDefault("ZEPPELIN_SPARK_CONCURRENTSQL",
"zeppelin.spark.concurrentSQL", "false"),
"Execute multiple SQL concurrently if set true.")
.add("zeppelin.spark.sql.stacktrace",
SparkInterpreter.getSystemDefault("ZEPPELIN_SPARK_SQL_STACKTRACE",
"zeppelin.spark.sql.stacktrace", "false"),
"Show full exception stacktrace for SQL queries if set to true.")
.build());
}
private String getJobGroup(InterpreterContext context){
return "zeppelin-" + context.getParagraphId();
}

View file

@ -32,6 +32,7 @@ import org.apache.spark.SparkContext;
import org.apache.spark.sql.SQLContext;
import org.apache.spark.sql.catalyst.expressions.Attribute;
import org.apache.spark.sql.hive.HiveContext;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.display.AngularObject;
import org.apache.zeppelin.display.AngularObjectRegistry;
import org.apache.zeppelin.display.AngularObjectWatcher;
@ -72,23 +73,28 @@ public class ZeppelinContext {
public HiveContext hiveContext;
private GUI gui;
@ZeppelinApi
public Object input(String name) {
return input(name, "");
}
@ZeppelinApi
public Object input(String name, Object defaultValue) {
return gui.input(name, defaultValue);
}
@ZeppelinApi
public Object select(String name, scala.collection.Iterable<Tuple2<Object, String>> options) {
return select(name, "", options);
}
@ZeppelinApi
public Object select(String name, Object defaultValue,
scala.collection.Iterable<Tuple2<Object, String>> options) {
return gui.select(name, defaultValue, tuplesToParamOptions(options));
}
@ZeppelinApi
public scala.collection.Iterable<Object> checkbox(String name,
scala.collection.Iterable<Tuple2<Object, String>> options) {
List<Object> allChecked = new LinkedList<Object>();
@ -98,6 +104,7 @@ public class ZeppelinContext {
return checkbox(name, collectionAsScalaIterable(allChecked), options);
}
@ZeppelinApi
public scala.collection.Iterable<Object> checkbox(String name,
scala.collection.Iterable<Object> defaultChecked,
scala.collection.Iterable<Tuple2<Object, String>> options) {
@ -143,6 +150,7 @@ public class ZeppelinContext {
* show DataFrame or SchemaRDD
* @param o DataFrame or SchemaRDD object
*/
@ZeppelinApi
public void show(Object o) {
show(o, maxResult);
}
@ -152,6 +160,8 @@ public class ZeppelinContext {
* @param o DataFrame or SchemaRDD object
* @param maxResult maximum number of rows to display
*/
@ZeppelinApi
public void show(Object o, int maxResult) {
Class cls = null;
try {
@ -267,6 +277,7 @@ public class ZeppelinContext {
* Run paragraph by id
* @param id
*/
@ZeppelinApi
public void run(String id) {
run(id, interpreterContext);
}
@ -276,6 +287,7 @@ public class ZeppelinContext {
* @param id
* @param context
*/
@ZeppelinApi
public void run(String id, InterpreterContext context) {
if (id.equals(context.getParagraphId())) {
throw new InterpreterException("Can not run current Paragraph");
@ -295,6 +307,7 @@ public class ZeppelinContext {
* Run paragraph at idx
* @param idx
*/
@ZeppelinApi
public void run(int idx) {
run(idx, interpreterContext);
}
@ -317,6 +330,7 @@ public class ZeppelinContext {
runner.run();
}
@ZeppelinApi
public void run(List<Object> paragraphIdOrIdx) {
run(paragraphIdOrIdx, interpreterContext);
}
@ -325,6 +339,7 @@ public class ZeppelinContext {
* Run paragraphs
* @param paragraphIdOrIdx list of paragraph id or idx
*/
@ZeppelinApi
public void run(List<Object> paragraphIdOrIdx, InterpreterContext context) {
for (Object idOrIdx : paragraphIdOrIdx) {
if (idOrIdx instanceof String) {
@ -339,6 +354,7 @@ public class ZeppelinContext {
}
}
@ZeppelinApi
public void runAll() {
runAll(interpreterContext);
}
@ -346,6 +362,7 @@ public class ZeppelinContext {
/**
* Run all paragraphs. except this.
*/
@ZeppelinApi
public void runAll(InterpreterContext context) {
for (InterpreterContextRunner r : context.getRunners()) {
if (r.getParagraphId().equals(context.getParagraphId())) {
@ -356,6 +373,7 @@ public class ZeppelinContext {
}
}
@ZeppelinApi
public List<String> listParagraphs() {
List<String> paragraphs = new LinkedList<String>();
@ -389,6 +407,7 @@ public class ZeppelinContext {
* @param name variable name
* @return value
*/
@ZeppelinApi
public Object angular(String name) {
AngularObject ao = getAngularObject(name, interpreterContext);
if (ao == null) {
@ -403,6 +422,7 @@ public class ZeppelinContext {
* @param name variable name
* @return value
*/
@Deprecated
public Object angularGlobal(String name) {
AngularObjectRegistry registry = interpreterContext.getAngularObjectRegistry();
AngularObject ao = registry.get(name, null, null);
@ -419,6 +439,7 @@ public class ZeppelinContext {
* @param name name of the variable
* @param o value
*/
@ZeppelinApi
public void angularBind(String name, Object o) {
angularBind(name, o, interpreterContext.getNoteId());
}
@ -429,6 +450,7 @@ public class ZeppelinContext {
* @param name name of the variable
* @param o value
*/
@Deprecated
public void angularBindGlobal(String name, Object o) {
angularBind(name, o, (String) null);
}
@ -440,6 +462,7 @@ public class ZeppelinContext {
* @param o value
* @param watcher watcher of the variable
*/
@ZeppelinApi
public void angularBind(String name, Object o, AngularObjectWatcher watcher) {
angularBind(name, o, interpreterContext.getNoteId(), watcher);
}
@ -451,6 +474,7 @@ public class ZeppelinContext {
* @param o value
* @param watcher watcher of the variable
*/
@Deprecated
public void angularBindGlobal(String name, Object o, AngularObjectWatcher watcher) {
angularBind(name, o, null, watcher);
}
@ -460,6 +484,7 @@ public class ZeppelinContext {
* @param name name of the variable
* @param watcher watcher
*/
@ZeppelinApi
public void angularWatch(String name, AngularObjectWatcher watcher) {
angularWatch(name, interpreterContext.getNoteId(), watcher);
}
@ -469,27 +494,31 @@ public class ZeppelinContext {
* @param name name of the variable
* @param watcher watcher
*/
@Deprecated
public void angularWatchGlobal(String name, AngularObjectWatcher watcher) {
angularWatch(name, null, watcher);
}
@ZeppelinApi
public void angularWatch(String name,
final scala.Function2<Object, Object, Unit> func) {
angularWatch(name, interpreterContext.getNoteId(), func);
}
@Deprecated
public void angularWatchGlobal(String name,
final scala.Function2<Object, Object, Unit> func) {
angularWatch(name, null, func);
}
@ZeppelinApi
public void angularWatch(
String name,
final scala.Function3<Object, Object, InterpreterContext, Unit> func) {
angularWatch(name, interpreterContext.getNoteId(), func);
}
@Deprecated
public void angularWatchGlobal(
String name,
final scala.Function3<Object, Object, InterpreterContext, Unit> func) {
@ -501,6 +530,7 @@ public class ZeppelinContext {
* @param name
* @param watcher
*/
@ZeppelinApi
public void angularUnwatch(String name, AngularObjectWatcher watcher) {
angularUnwatch(name, interpreterContext.getNoteId(), watcher);
}
@ -510,6 +540,7 @@ public class ZeppelinContext {
* @param name
* @param watcher
*/
@Deprecated
public void angularUnwatchGlobal(String name, AngularObjectWatcher watcher) {
angularUnwatch(name, null, watcher);
}
@ -519,6 +550,7 @@ public class ZeppelinContext {
* Remove all watchers for the angular variable (local)
* @param name
*/
@ZeppelinApi
public void angularUnwatch(String name) {
angularUnwatch(name, interpreterContext.getNoteId());
}
@ -527,6 +559,7 @@ public class ZeppelinContext {
* Remove all watchers for the angular variable (global)
* @param name
*/
@Deprecated
public void angularUnwatchGlobal(String name) {
angularUnwatch(name, (String) null);
}
@ -535,6 +568,7 @@ public class ZeppelinContext {
* Remove angular variable and all the watchers.
* @param name
*/
@ZeppelinApi
public void angularUnbind(String name) {
String noteId = interpreterContext.getNoteId();
angularUnbind(name, noteId);
@ -544,6 +578,7 @@ public class ZeppelinContext {
* Remove angular variable and all the watchers.
* @param name
*/
@Deprecated
public void angularUnbindGlobal(String name) {
angularUnbind(name, null);
}
@ -661,6 +696,7 @@ public class ZeppelinContext {
* @param name
* @param value
*/
@ZeppelinApi
public void put(String name, Object value) {
ResourcePool resourcePool = interpreterContext.getResourcePool();
resourcePool.put(name, value);
@ -672,6 +708,7 @@ public class ZeppelinContext {
* @param name
* @return null if resource not found
*/
@ZeppelinApi
public Object get(String name) {
ResourcePool resourcePool = interpreterContext.getResourcePool();
Resource resource = resourcePool.get(name);
@ -686,6 +723,7 @@ public class ZeppelinContext {
* Remove object from resourcePool
* @param name
*/
@ZeppelinApi
public void remove(String name) {
ResourcePool resourcePool = interpreterContext.getResourcePool();
resourcePool.remove(name);
@ -696,6 +734,7 @@ public class ZeppelinContext {
* @param name
* @return
*/
@ZeppelinApi
public boolean containsKey(String name) {
ResourcePool resourcePool = interpreterContext.getResourcePool();
Resource resource = resourcePool.get(name);
@ -705,6 +744,7 @@ public class ZeppelinContext {
/**
* Get all resources
*/
@ZeppelinApi
public ResourceSet getAll() {
ResourcePool resourcePool = interpreterContext.getResourcePool();
return resourcePool.getAll();

View file

@ -0,0 +1,146 @@
[
{
"group": "spark",
"name": "spark",
"className": "org.apache.zeppelin.spark.SparkInterpreter",
"properties": {
"spark.executor.memory": {
"envName": null,
"propertyName": "spark.executor.memory",
"defaultValue": "",
"description": "Executor memory per worker instance. ex) 512m, 32g"
},
"args": {
"envName": null,
"propertyName": null,
"defaultValue": "",
"description": "spark commandline args"
},
"zeppelin.spark.useHiveContext": {
"envName": "ZEPPELIN_SPARK_USEHIVECONTEXT",
"propertyName": "zeppelin.spark.useHiveContext",
"defaultValue": "true",
"description": "Use HiveContext instead of SQLContext if it is true."
},
"spark.app.name": {
"envName": "SPARK_APP_NAME",
"propertyName": "spark.app.name",
"defaultValue": "Zeppelin",
"description": "The name of spark application."
},
"zeppelin.spark.printREPLOutput": {
"envName": null,
"propertyName": null,
"defaultValue": "true",
"description": "Print REPL output"
},
"spark.cores.max": {
"envName": null,
"propertyName": "spark.cores.max",
"defaultValue": "",
"description": "Total number of cores to use. Empty value uses all available core."
},
"zeppelin.spark.maxResult": {
"envName": "ZEPPELIN_SPARK_MAXRESULT",
"propertyName": "zeppelin.spark.maxResult",
"defaultValue": "1000",
"description": "Max number of SparkSQL result to display."
},
"master": {
"envName": "MASTER",
"propertyName": "spark.master",
"defaultValue": "local[*]",
"description": "Spark master uri. ex) spark://masterhost:7077"
}
}
},
{
"group": "spark",
"name": "sql",
"className": "org.apache.zeppelin.spark.SparkSqlInterpreter",
"properties": {
"zeppelin.spark.concurrentSQL": {
"envName": "ZEPPELIN_SPARK_CONCURRENTSQL",
"propertyName": "zeppelin.spark.concurrentSQL",
"defaultValue": "false",
"description": "Execute multiple SQL concurrently if set true."
},
"zeppelin.spark.sql.stacktrace": {
"envName": "ZEPPELIN_SPARK_SQL_STACKTRACE",
"propertyName": "zeppelin.spark.sql.stacktrace",
"defaultValue": "false",
"description": "Show full exception stacktrace for SQL queries if set to true."
},
"zeppelin.spark.maxResult": {
"envName": "ZEPPELIN_SPARK_MAXRESULT",
"propertyName": "zeppelin.spark.maxResult",
"defaultValue": "1000",
"description": "Max number of SparkSQL result to display."
}
}
},
{
"group": "spark",
"name": "dep",
"className": "org.apache.zeppelin.spark.DepInterpreter",
"properties": {
"zeppelin.dep.localrepo": {
"envName": "ZEPPELIN_DEP_LOCALREPO",
"propertyName": null,
"defaultValue": "local-repo",
"description": "local repository for dependency loader"
},
"zeppelin.dep.additionalRemoteRepository": {
"envName": null,
"propertyName": null,
"defaultValue": "spark-packages,http://dl.bintray.com/spark-packages/maven,false;",
"description": "A list of 'id,remote-repository-URL,is-snapshot;' for each remote repository."
}
}
},
{
"group": "spark",
"name": "pyspark",
"className": "org.apache.zeppelin.spark.PySparkInterpreter",
"properties": {
"zeppelin.pyspark.python": {
"envName": "PYSPARK_PYTHON",
"propertyName": null,
"defaultValue": "python",
"description": "Python command to run pyspark with"
}
}
},
{
"group": "spark",
"name": "r",
"className": "org.apache.zeppelin.spark.SparkRInterpreter",
"properties": {
"zeppelin.R.knitr": {
"envName": "ZEPPELIN_R_KNITR",
"propertyName": "zeppelin.R.knitr",
"defaultValue": "true",
"description": "whether use knitr or not"
},
"zeppelin.R.cmd": {
"envName": "ZEPPELIN_R_CMD",
"propertyName": "zeppelin.R.cmd",
"defaultValue": "R",
"description": "R repl path"
},
"zeppelin.R.image.width": {
"envName": "ZEPPELIN_R_IMAGE_WIDTH",
"propertyName": "zeppelin.R.image.width",
"defaultValue": "100%",
"description": ""
},
"zeppelin.R.render.options": {
"envName": "ZEPPELIN_R_RENDER_OPTIONS",
"propertyName": "zeppelin.R.render.options",
"defaultValue": "out.format = 'html', comment = NA, echo = FALSE, results = 'asis', message = F, warning = F",
"description": ""
}
}
}
]

View file

@ -68,18 +68,18 @@ object ZeppelinRDisplay {
}
private def textDisplay(body: Element): RDisplay = {
RDisplay(body.getElementsByTag("p").get(0).html(), TEXT, SUCCESS)
RDisplay(body.getElementsByTag("p").first().html(), TEXT, SUCCESS)
}
private def tableDisplay(body: Element): RDisplay = {
val p = body.getElementsByTag("p").get(0).html.replace("“%table " , "").replace("”", "")
val p = body.getElementsByTag("p").first().html.replace("“%table " , "").replace("”", "")
val r = (pattern findFirstIn p).getOrElse("")
val table = p.replace(r, "").replace("\\t", "\t").replace("\\n", "\n")
RDisplay(table, TABLE, SUCCESS)
}
private def imgDisplay(body: Element): RDisplay = {
val p = body.getElementsByTag("p").get(0).html.replace("“%img " , "").replace("”", "")
val p = body.getElementsByTag("p").first().html.replace("“%img " , "").replace("”", "")
val r = (pattern findFirstIn p).getOrElse("")
val img = p.replace(r, "")
RDisplay(img, IMG, SUCCESS)

View file

@ -39,6 +39,13 @@ public class DepInterpreterTest {
private File tmpDir;
private SparkInterpreter repl;
private Properties getTestProperties() {
Properties p = new Properties();
p.setProperty("zeppelin.dep.localrepo", "local-repo");
p.setProperty("zeppelin.dep.additionalRemoteRepository", "spark-packages,http://dl.bintray.com/spark-packages/maven,false;");
return p;
}
@Before
public void setUp() throws Exception {
tmpDir = new File(System.getProperty("java.io.tmpdir") + "/ZeppelinLTest_" + System.currentTimeMillis());
@ -46,7 +53,7 @@ public class DepInterpreterTest {
tmpDir.mkdirs();
Properties p = new Properties();
Properties p = getTestProperties();
dep = new DepInterpreter(p);
dep.open();

View file

@ -64,6 +64,16 @@ public class SparkInterpreterTest {
return version;
}
public static Properties getSparkTestProperties() {
Properties p = new Properties();
p.setProperty("master", "local[*]");
p.setProperty("spark.app.name", "Zeppelin Test");
p.setProperty("zeppelin.spark.useHiveContext", "true");
p.setProperty("zeppelin.spark.maxResult", "1000");
return p;
}
@Before
public void setUp() throws Exception {
tmpDir = new File(System.getProperty("java.io.tmpdir") + "/ZeppelinLTest_" + System.currentTimeMillis());
@ -72,10 +82,9 @@ public class SparkInterpreterTest {
tmpDir.mkdirs();
if (repl == null) {
Properties p = new Properties();
intpGroup = new InterpreterGroup();
intpGroup.put("note", new LinkedList<Interpreter>());
repl = new SparkInterpreter(p);
repl = new SparkInterpreter(getSparkTestProperties());
repl.setInterpreterGroup(intpGroup);
intpGroup.get("note").add(repl);
repl.open();
@ -208,8 +217,7 @@ public class SparkInterpreterTest {
@Test
public void shareSingleSparkContext() throws InterruptedException {
// create another SparkInterpreter
Properties p = new Properties();
SparkInterpreter repl2 = new SparkInterpreter(p);
SparkInterpreter repl2 = new SparkInterpreter(getSparkTestProperties());
repl2.setInterpreterGroup(intpGroup);
intpGroup.get("note").add(repl2);
repl2.open();

View file

@ -47,6 +47,10 @@ public class SparkSqlInterpreterTest {
@Before
public void setUp() throws Exception {
Properties p = new Properties();
p.putAll(SparkInterpreterTest.getSparkTestProperties());
p.setProperty("zeppelin.spark.maxResult", "1000");
p.setProperty("zeppelin.spark.concurrentSQL", "false");
p.setProperty("zeppelin.spark.sql.stacktrace", "false");
if (repl == null) {

View file

@ -21,14 +21,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-tajo</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Tajo interpreter</name>
<url>http://www.apache.org</url>

View file

@ -22,16 +22,16 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-display</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Display system apis</name>
<url>http://incubator.zeppelin.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<scala.version>2.10.4</scala.version>

View file

@ -18,6 +18,7 @@ package org.apache.zeppelin.display.angular
import java.io.PrintStream
import org.apache.zeppelin.annotation.ZeppelinApi
import org.apache.zeppelin.display.{AngularObjectWatcher, AngularObject}
import org.apache.zeppelin.interpreter.{InterpreterResult, InterpreterContext}
@ -41,28 +42,34 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
/**
* On click element
*
* @param callback
* @return
*/
@ZeppelinApi
def onClick(callback: () => Unit): AbstractAngularElem = {
onEvent("ng-click", callback)
}
/**
* On
*
* @param callback
* @return
*/
@ZeppelinApi
def onChange(callback: () => Unit): AbstractAngularElem = {
onEvent("ng-change", callback)
}
/**
* Bind angularObject to ng-model directive
*
* @param name name of angularObject
* @param value initialValue
* @return
*/
@ZeppelinApi
def model(name: String, value: Any): AbstractAngularElem = {
val registry = interpreterContext.getAngularObjectRegistry
@ -82,6 +89,7 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
}
@ZeppelinApi
def model(name: String): AbstractAngularElem = {
val registry = interpreterContext.getAngularObjectRegistry
@ -99,8 +107,10 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
/**
* Retrieve value of model
*
* @return
*/
@ZeppelinApi
def model(): Any = {
if (angularObjects.contains(modelName)) {
angularObjects(modelName).get()
@ -114,6 +124,7 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
* @param eventName angular directive like ng-click, ng-change, etc.
* @return
*/
@ZeppelinApi
def onEvent(eventName: String, callback: () => Unit): AbstractAngularElem = {
val registry = interpreterContext.getAngularObjectRegistry
@ -151,12 +162,14 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
* disassociate this element and it's child from front-end
* by removing angularobject
*/
@ZeppelinApi
def disassociate() = {
remove(this)
}
/**
* Remove all angularObject recursively
*
* @param node
*/
private def remove(node: Node): Unit = {
@ -172,8 +185,10 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
/**
* Print into provided print stream
*
* @return
*/
@ZeppelinApi
def display(out: java.io.PrintStream): Unit = {
out.print(this.toString)
out.flush()
@ -182,6 +197,7 @@ abstract class AbstractAngularElem(val interpreterContext: InterpreterContext,
/**
* Print into InterpreterOutput
*/
@ZeppelinApi
def display(): Unit = {
val out = interpreterContext.out
out.setType(InterpreterResult.Type.ANGULAR)

View file

@ -16,6 +16,7 @@
*/
package org.apache.zeppelin.display.angular
import org.apache.zeppelin.annotation.ZeppelinApi
import org.apache.zeppelin.display.AngularObject
import org.apache.zeppelin.interpreter.InterpreterContext
@ -29,9 +30,11 @@ abstract class AbstractAngularModel(name: String) {
/**
* Create AngularModel with initial Value
*
* @param name name of model
* @param newValue value
*/
@ZeppelinApi
def this(name: String, newValue: Any) = {
this(name)
value(newValue)
@ -42,16 +45,20 @@ abstract class AbstractAngularModel(name: String) {
/**
* Get value of the model
*
* @return
*/
@ZeppelinApi
def apply(): Any = {
value()
}
/**
* Get value of the model
*
* @return
*/
@ZeppelinApi
def value(): Any = {
val angularObject = getAngularObject()
if (angularObject == null) {
@ -61,7 +68,7 @@ abstract class AbstractAngularModel(name: String) {
}
}
@ZeppelinApi
def apply(newValue: Any): Unit = {
value(newValue)
}
@ -69,8 +76,10 @@ abstract class AbstractAngularModel(name: String) {
/**
* Set value of the model
*
* @param newValue
*/
@ZeppelinApi
def value(newValue: Any): Unit = {
var angularObject = getAngularObject()
if (angularObject == null) {
@ -82,6 +91,7 @@ abstract class AbstractAngularModel(name: String) {
angularObject.get()
}
@ZeppelinApi
def remove(): Any = {
val angularObject = getAngularObject()

View file

@ -23,7 +23,7 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>

View file

@ -121,7 +121,6 @@ The text of each license is also included at licenses/LICENSE-[project]-[version
(The MIT License) Angular Websocket v1.0.13 (http://angularclass.github.io/angular-websocket/) - https://github.com/AngularClass/angular-websocket/blob/v1.0.13/LICENSE
(The MIT License) UI.Ace v0.1.1 (http://angularclass.github.io/angular-websocket/) - https://github.com/angular-ui/ui-ace/blob/master/LICENSE
(The MIT License) jquery.scrollTo v1.4.13 (https://github.com/flesler/jquery.scrollTo) - https://github.com/flesler/jquery.scrollTo/blob/1.4.13/LICENSE
(The MIT License) jquery.floatThead v1.3.2 (https://github.com/mkoryak/floatThead) - https://github.com/mkoryak/floatThead/blob/master/license.txt
(The MIT License) angular-dragdrop v1.0.8 (http://codef0rmer.github.io/angular-dragdrop/#/) - https://github.com/codef0rmer/angular-dragdrop/blob/v1.0.8/LICENSE
(The MIT License) perfect-scrollbar v0.5.4 (http://noraesae.github.io/perfect-scrollbar/) - https://github.com/noraesae/perfect-scrollbar/tree/0.5.4
(The MIT License) ng-sortable v1.1.9 (https://github.com/a5hik/ng-sortable) - https://github.com/a5hik/ng-sortable/blob/1.1.9/LICENSE

View file

@ -0,0 +1,26 @@
Copyright (c) 2009-2016, Barthelemy Dagenais and individual contributors. All
rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
- The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -24,17 +24,17 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-interpreter</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Interpreter</name>
<description>Zeppelin Interpreter</description>
<url>http://zeppelin.incubator.apache.org</url>
<url>http://zeppelin.apache.org</url>
<properties>
<commons-lang.version>3.4</commons-lang.version>

View file

@ -0,0 +1,32 @@
/*
* 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.
*/
package org.apache.zeppelin.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Experimental API
* Might change or be removed at anytime, or be adopted as ZeppelinApi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE, ElementType.PACKAGE})
public @interface Experimental {
}

View file

@ -0,0 +1,31 @@
/*
* 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.
*/
package org.apache.zeppelin.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* APIs exposed to extends pluggable components or exposed to enduser
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE, ElementType.PACKAGE})
public @interface ZeppelinApi {
}

View file

@ -25,6 +25,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.google.gson.annotations.SerializedName;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.scheduler.Scheduler;
import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.slf4j.Logger;
@ -35,7 +37,7 @@ import org.slf4j.LoggerFactory;
* If you want to implement new Zeppelin interpreter, extend this class
*
* Please see,
* https://zeppelin.incubator.apache.org/docs/latest/development/writingzeppelininterpreter.html
* https://zeppelin.apache.org/docs/latest/development/writingzeppelininterpreter.html
*
* open(), close(), interpreter() is three the most important method you need to implement.
* cancel(), getProgress(), completion() is good to have
@ -48,12 +50,14 @@ public abstract class Interpreter {
* Opens interpreter. You may want to place your initialize routine here.
* open() is called only once
*/
@ZeppelinApi
public abstract void open();
/**
* Closes interpreter. You may want to free your resources up here.
* close() is called only once
*/
@ZeppelinApi
public abstract void close();
/**
@ -63,6 +67,7 @@ public abstract class Interpreter {
* @param context
* @return
*/
@ZeppelinApi
public abstract InterpreterResult interpret(String st, InterpreterContext context);
/**
@ -70,15 +75,17 @@ public abstract class Interpreter {
*
* @param context
*/
@ZeppelinApi
public abstract void cancel(InterpreterContext context);
/**
* Dynamic form handling
* see http://zeppelin.incubator.apache.org/docs/dynamicform.html
* see http://zeppelin.apache.org/docs/dynamicform.html
*
* @return FormType.SIMPLE enables simple pattern replacement (eg. Hello ${name=world}),
* FormType.NATIVE handles form in API
*/
@ZeppelinApi
public abstract FormType getFormType();
/**
@ -87,6 +94,7 @@ public abstract class Interpreter {
* @param context
* @return number between 0-100
*/
@ZeppelinApi
public abstract int getProgress(InterpreterContext context);
/**
@ -97,6 +105,7 @@ public abstract class Interpreter {
* @param cursor cursor position in statements
* @return list of possible completion. Return empty list if there're nothing to return.
*/
@ZeppelinApi
public abstract List<String> completion(String buf, int cursor);
/**
@ -113,6 +122,7 @@ public abstract class Interpreter {
* This method can be called multiple times and have to return the same instance.
* Can not return null.
*/
@ZeppelinApi
public Scheduler getScheduler() {
return SchedulerFactory.singleton().createOrGetFIFOScheduler("interpreter_" + this.hashCode());
}
@ -120,6 +130,7 @@ public abstract class Interpreter {
/**
* Called when interpreter is no longer used.
*/
@ZeppelinApi
public void destroy() {
}
@ -128,7 +139,9 @@ public abstract class Interpreter {
private URL [] classloaderUrls;
protected Properties property;
@ZeppelinApi
public Interpreter(Properties property) {
logger.debug("Properties: {}", property);
this.property = property;
}
@ -136,17 +149,21 @@ public abstract class Interpreter {
this.property = property;
}
@ZeppelinApi
public Properties getProperty() {
Properties p = new Properties();
p.putAll(property);
Map<String, InterpreterProperty> defaultProperties = Interpreter
.findRegisteredInterpreterByClassName(getClassName()).getProperties();
for (String k : defaultProperties.keySet()) {
if (!p.containsKey(k)) {
String value = defaultProperties.get(k).getDefaultValue();
if (value != null) {
p.put(k, defaultProperties.get(k).getDefaultValue());
RegisteredInterpreter registeredInterpreter = Interpreter.findRegisteredInterpreterByClassName(
getClassName());
if (null != registeredInterpreter) {
Map<String, InterpreterProperty> defaultProperties = registeredInterpreter.getProperties();
for (String k : defaultProperties.keySet()) {
if (!p.containsKey(k)) {
String value = defaultProperties.get(k).getValue();
if (value != null) {
p.put(k, defaultProperties.get(k).getValue());
}
}
}
}
@ -154,18 +171,11 @@ public abstract class Interpreter {
return p;
}
@ZeppelinApi
public String getProperty(String key) {
if (property.containsKey(key)) {
return property.getProperty(key);
}
logger.debug("key: {}, value: {}", key, getProperty().getProperty(key));
Map<String, InterpreterProperty> defaultProperties = Interpreter
.findRegisteredInterpreterByClassName(getClassName()).getProperties();
if (defaultProperties.containsKey(key)) {
return defaultProperties.get(key).getDefaultValue();
}
return null;
return getProperty().getProperty(key);
}
@ -177,6 +187,7 @@ public abstract class Interpreter {
this.interpreterGroup = interpreterGroup;
}
@ZeppelinApi
public InterpreterGroup getInterpreterGroup() {
return this.interpreterGroup;
}
@ -189,6 +200,7 @@ public abstract class Interpreter {
this.classloaderUrls = classloaderUrls;
}
@ZeppelinApi
public Interpreter getInterpreterInTheSameSessionByClassName(String className) {
synchronized (interpreterGroup) {
for (List<Interpreter> interpreters : interpreterGroup.values()) {
@ -228,8 +240,11 @@ public abstract class Interpreter {
* Represent registered interpreter class
*/
public static class RegisteredInterpreter {
private String name;
//@SerializedName("interpreterGroup")
private String group;
//@SerializedName("interpreterName")
private String name;
//@SerializedName("interpreterClassName")
private String className;
private Map<String, InterpreterProperty> properties;
private String path;
@ -267,6 +282,10 @@ public abstract class Interpreter {
return path;
}
public String getInterpreterKey() {
return getGroup() + "." + getName();
}
}
/**
@ -287,10 +306,21 @@ public abstract class Interpreter {
register(name, group, className, new HashMap<String, InterpreterProperty>());
}
@Deprecated
public static void register(String name, String group, String className,
Map<String, InterpreterProperty> properties) {
registeredInterpreters.put(group + "." + name, new RegisteredInterpreter(
name, group, className, properties));
Map<String, InterpreterProperty> properties) {
logger.error("Static initialization is deprecated. You should change it to use " +
"interpreter-setting.json in your jar or " +
"interpreter/{interpreter}/interpreter-setting.json");
register(new RegisteredInterpreter(name, group, className, properties));
}
public static void register(RegisteredInterpreter registeredInterpreter) {
// TODO(jongyoul): Error should occur when two same interpreter key with different settings
String interpreterKey = registeredInterpreter.getInterpreterKey();
if (!registeredInterpreters.containsKey(interpreterKey)) {
registeredInterpreters.put(interpreterKey, registeredInterpreter);
}
}
public static RegisteredInterpreter findRegisteredInterpreterByClassName(String className) {

View file

@ -20,6 +20,7 @@ package org.apache.zeppelin.interpreter;
import java.util.List;
import java.util.Map;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.display.AngularObjectRegistry;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.apache.zeppelin.display.GUI;
@ -31,6 +32,7 @@ import org.apache.zeppelin.resource.ResourcePool;
public class InterpreterContext {
private static final ThreadLocal<InterpreterContext> threadIC =
new ThreadLocal<InterpreterContext>();
public final InterpreterOutput out;
public static InterpreterContext get() {

View file

@ -21,16 +21,39 @@ package org.apache.zeppelin.interpreter;
* Represent property of interpreter
*/
public class InterpreterProperty {
String envName;
String propertyName;
String defaultValue;
String description;
public InterpreterProperty(String defaultValue,
String description) {
super();
public InterpreterProperty(String envName, String propertyName, String defaultValue,
String description) {
this.envName = envName;
this.propertyName = propertyName;
this.defaultValue = defaultValue;
this.description = description;
}
public InterpreterProperty(String defaultValue, String description) {
this(null, null, defaultValue, description);
}
public String getEnvName() {
return envName;
}
public void setEnvName(String envName) {
this.envName = envName;
}
public String getPropertyName() {
return propertyName;
}
public void setPropertyName(String propertyName) {
this.propertyName = propertyName;
}
public String getDefaultValue() {
return defaultValue;
}
@ -46,4 +69,28 @@ public class InterpreterProperty {
public void setDescription(String description) {
this.description = description;
}
public String getValue() {
//TODO(jongyoul): Remove SparkInterpreter's getSystemDefault method
if (envName != null && !envName.isEmpty()) {
String envValue = System.getenv().get(envName);
if (envValue != null) {
return envValue;
}
}
if (propertyName != null && !propertyName.isEmpty()) {
String propValue = System.getProperty(propertyName);
if (propValue != null) {
return propValue;
}
}
return defaultValue;
}
@Override
public String toString() {
return String.format("{envName=%s, propertyName=%s, defaultValue=%s, description=%20s", envName,
propertyName, defaultValue, description);
}
}

View file

@ -230,9 +230,10 @@ public class RemoteInterpreter extends Interpreter {
}
} catch (TException e) {
broken = true;
logger.error("Failed to create interpreter: {}", getClassName());
throw new InterpreterException(e);
} finally {
// TODO(jongyoul): Fixed it when not all of interpreter in same interpreter group are broken
interpreterProcess.releaseClient(client, broken);
}
}
@ -248,12 +249,18 @@ public class RemoteInterpreter extends Interpreter {
synchronized (interpreterGroup) {
// initialize all interpreters in this interpreter group
List<Interpreter> interpreters = interpreterGroup.get(noteId);
for (Interpreter intp : interpreters) {
for (Interpreter intp : new ArrayList<>(interpreters)) {
Interpreter p = intp;
while (p instanceof WrappedInterpreter) {
p = ((WrappedInterpreter) p).getInnerInterpreter();
}
((RemoteInterpreter) p).init();
try {
((RemoteInterpreter) p).init();
} catch (InterpreterException e) {
logger.error("Failed to initialize interpreter: {}. Remove it from interpreterGroup",
p.getClassName());
interpreters.remove(p);
}
}
}
}

View file

@ -24,6 +24,7 @@ package org.apache.zeppelin.user;
public class AuthenticationInfo {
String user;
String ticket;
UserCredentials userCredentials;
public AuthenticationInfo() {}
@ -52,4 +53,13 @@ public class AuthenticationInfo {
public void setTicket(String ticket) {
this.ticket = ticket;
}
public UserCredentials getUserCredentials() {
return userCredentials;
}
public void setUserCredentials(UserCredentials userCredentials) {
this.userCredentials = userCredentials;
}
}

View file

@ -0,0 +1,122 @@
/*
* 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.
*/
package org.apache.zeppelin.user;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* Class defining credentials for data source authorization
*/
public class Credentials {
private static final Logger LOG = LoggerFactory.getLogger(Credentials.class);
private Map<String, UserCredentials> credentialsMap;
private Gson gson;
private Boolean credentialsPersist = true;
File credentialsFile;
public Credentials(Boolean credentialsPersist, String credentialsPath) {
this.credentialsPersist = credentialsPersist;
if (credentialsPath != null) {
credentialsFile = new File(credentialsPath);
}
credentialsMap = new HashMap<>();
if (credentialsPersist) {
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
gson = builder.create();
loadFromFile();
}
}
public UserCredentials getUserCredentials(String username) {
UserCredentials uc = credentialsMap.get(username);
if (uc == null) {
uc = new UserCredentials();
}
return uc;
}
public void putUserCredentials(String username, UserCredentials uc) throws IOException {
credentialsMap.put(username, uc);
if (credentialsPersist) {
saveToFile();
}
}
private void loadFromFile() {
LOG.info(credentialsFile.getAbsolutePath());
if (!credentialsFile.exists()) {
// nothing to read
return;
}
try {
FileInputStream fis = new FileInputStream(credentialsFile);
InputStreamReader isr = new InputStreamReader(fis);
BufferedReader bufferedReader = new BufferedReader(isr);
StringBuilder sb = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null) {
sb.append(line);
}
isr.close();
fis.close();
String json = sb.toString();
CredentialsInfoSaving info = gson.fromJson(json, CredentialsInfoSaving.class);
this.credentialsMap = info.credentialsMap;
} catch (IOException e) {
LOG.error("Error loading credentials file", e);
e.printStackTrace();
}
}
private void saveToFile() throws IOException {
String jsonString;
synchronized (credentialsMap) {
CredentialsInfoSaving info = new CredentialsInfoSaving();
info.credentialsMap = credentialsMap;
jsonString = gson.toJson(info);
}
try {
if (!credentialsFile.exists()) {
credentialsFile.createNewFile();
}
FileOutputStream fos = new FileOutputStream(credentialsFile, false);
OutputStreamWriter out = new OutputStreamWriter(fos);
out.append(jsonString);
out.close();
fos.close();
} catch (IOException e) {
LOG.error("Error saving credentials file", e);
}
}
}

View file

@ -0,0 +1,27 @@
/*
* 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.
*/
package org.apache.zeppelin.user;
import java.util.Map;
/**
* Helper class to save credentials
*/
public class CredentialsInfoSaving {
public Map<String, UserCredentials> credentialsMap;
}

View file

@ -0,0 +1,47 @@
/*
* 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.
*/
package org.apache.zeppelin.user;
import java.util.HashMap;
import java.util.Map;
/**
* User Credentials POJO
*/
public class UserCredentials {
private Map<String, UsernamePassword> userCredentials;
public UserCredentials() {
this.userCredentials = new HashMap<>();
}
public UsernamePassword getUsernamePassword(String entity) {
return userCredentials.get(entity);
}
public void putUsernamePassword(String entity, UsernamePassword up) {
userCredentials.put(entity, up);
}
@Override
public String toString() {
return "UserCredentials{" +
"userCredentials=" + userCredentials +
'}';
}
}

View file

@ -0,0 +1,55 @@
/*
* 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.
*/
package org.apache.zeppelin.user;
/**
* Username and Password POJO
*/
public class UsernamePassword {
private String username;
private String password;
public UsernamePassword(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "UsernamePassword{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}

View file

@ -0,0 +1,40 @@
/*
* 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.
*/
package org.apache.zeppelin.user;
import static org.junit.Assert.*;
import org.junit.Test;
import java.io.IOException;
public class CredentialsTest {
@Test
public void testDefaultProperty() throws IOException {
Credentials credentials = new Credentials(false, null);
UserCredentials userCredentials = new UserCredentials();
UsernamePassword up1 = new UsernamePassword("user2", "password");
userCredentials.putUsernamePassword("hive(vertica)", up1);
credentials.putUserCredentials("user1", userCredentials);
UserCredentials uc2 = credentials.getUserCredentials("user1");
UsernamePassword up2 = uc2.getUsernamePassword("hive(vertica)");
assertEquals(up1.getUsername(), up2.getUsername());
assertEquals(up1.getPassword(), up2.getPassword());
}
}

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-server</artifactId>
<packaging>jar</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: Server</name>
<url>http://www.nflabs.com</url>
@ -247,12 +247,6 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-exec</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency> <!-- because there are two of them above -->

View file

@ -17,6 +17,7 @@
package org.apache.zeppelin.rest;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.notebook.Notebook;
import org.apache.zeppelin.server.JsonResponse;
@ -46,6 +47,7 @@ public class ConfigurationsRestApi {
@GET
@Path("all")
@ZeppelinApi
public Response getAll() {
ZeppelinConfiguration conf = notebook.getConf();
@ -67,6 +69,7 @@ public class ConfigurationsRestApi {
@GET
@Path("prefix/{prefix}")
@ZeppelinApi
public Response getByPrefix(@PathParam("prefix") final String prefix) {
ZeppelinConfiguration conf = notebook.getConf();

View file

@ -0,0 +1,78 @@
/*
* 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.
*/
package org.apache.zeppelin.rest;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.zeppelin.user.Credentials;
import org.apache.zeppelin.user.UserCredentials;
import org.apache.zeppelin.user.UsernamePassword;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import java.io.IOException;
import java.util.Map;
/**
* Credential Rest API
*
*/
@Path("/credential")
@Produces("application/json")
public class CredentialRestApi {
Logger logger = LoggerFactory.getLogger(CredentialRestApi.class);
private Credentials credentials;
private Gson gson = new Gson();
@Context
private HttpServletRequest servReq;
public CredentialRestApi() {
}
public CredentialRestApi(Credentials credentials) {
this.credentials = credentials;
}
/**
* Update credentials for current user
*/
@PUT
public Response putCredentials(String message) throws IOException {
Map<String, String> messageMap = gson.fromJson(message,
new TypeToken<Map<String, String>>(){}.getType());
String entity = messageMap.get("entity");
String username = messageMap.get("username");
String password = messageMap.get("password");
String user = SecurityUtils.getPrincipal();
logger.info("Update credentials for user {} entity {}", user, entity);
UserCredentials uc = credentials.getUserCredentials(user);
uc.putUsernamePassword(entity, new UsernamePassword(username, password));
credentials.putUserCredentials(user, uc);
return new JsonResponse(Status.OK, "", "").build();
}
}

View file

@ -33,6 +33,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.dep.Repository;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.Interpreter.RegisteredInterpreter;
@ -73,6 +74,7 @@ public class InterpreterRestApi {
*/
@GET
@Path("setting")
@ZeppelinApi
public Response listSettings() {
List<InterpreterSetting> interpreterSettings = null;
interpreterSettings = interpreterFactory.get();
@ -88,6 +90,7 @@ public class InterpreterRestApi {
*/
@POST
@Path("setting")
@ZeppelinApi
public Response newSettings(String message) {
try {
NewInterpreterSettingRequest request = gson.fromJson(message,
@ -118,6 +121,7 @@ public class InterpreterRestApi {
@PUT
@Path("setting/{settingId}")
@ZeppelinApi
public Response updateSetting(String message, @PathParam("settingId") String settingId) {
logger.info("Update interpreterSetting {}", settingId);
@ -149,6 +153,7 @@ public class InterpreterRestApi {
*/
@DELETE
@Path("setting/{settingId}")
@ZeppelinApi
public Response removeSetting(@PathParam("settingId") String settingId) throws IOException {
logger.info("Remove interpreterSetting {}", settingId);
interpreterFactory.remove(settingId);
@ -160,6 +165,7 @@ public class InterpreterRestApi {
*/
@PUT
@Path("setting/restart/{settingId}")
@ZeppelinApi
public Response restartSetting(@PathParam("settingId") String settingId) {
logger.info("Restart interpreterSetting {}", settingId);
try {
@ -180,6 +186,7 @@ public class InterpreterRestApi {
* List all available interpreters by group
*/
@GET
@ZeppelinApi
public Response listInterpreter(String message) {
Map<String, RegisteredInterpreter> m = Interpreter.registeredInterpreters;
return new JsonResponse(Status.OK, "", m).build();
@ -191,6 +198,7 @@ public class InterpreterRestApi {
*/
@GET
@Path("repository")
@ZeppelinApi
public Response listRepositories() {
List<RemoteRepository> interpreterRepositories = null;
interpreterRepositories = interpreterFactory.getRepositories();
@ -204,6 +212,7 @@ public class InterpreterRestApi {
*/
@POST
@Path("repository")
@ZeppelinApi
public Response addRepository(String message) {
try {
Repository request = gson.fromJson(message, Repository.class);
@ -228,6 +237,7 @@ public class InterpreterRestApi {
*/
@DELETE
@Path("repository/{repoId}")
@ZeppelinApi
public Response removeRepository(@PathParam("repoId") String repoId) {
logger.info("Remove repository {}", repoId);
try {

View file

@ -19,6 +19,7 @@ package org.apache.zeppelin.rest;
import org.apache.shiro.authc.*;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.ticket.TicketContainer;
import org.apache.zeppelin.utils.SecurityUtils;
@ -60,6 +61,7 @@ public class LoginRestApi {
* @return 200 response
*/
@POST
@ZeppelinApi
public Response postLogin(@FormParam("userName") String userName,
@FormParam("password") String password) {
JsonResponse response = null;
@ -113,6 +115,7 @@ public class LoginRestApi {
@POST
@Path("logout")
@ZeppelinApi
public Response logout() {
JsonResponse response;

View file

@ -32,6 +32,7 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang3.StringUtils;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.interpreter.InterpreterSetting;
import org.apache.zeppelin.notebook.Note;
import org.apache.zeppelin.notebook.Notebook;
@ -83,6 +84,7 @@ public class NotebookRestApi {
*/
@GET
@Path("{noteId}/permissions")
@ZeppelinApi
public Response getNotePermissions(@PathParam("noteId") String noteId) {
Note note = notebook.getNote(noteId);
HashMap<String, Set<String>> permissionsMap = new HashMap();
@ -106,6 +108,7 @@ public class NotebookRestApi {
*/
@PUT
@Path("{noteId}/permissions")
@ZeppelinApi
public Response putNotePermissions(@PathParam("noteId") String noteId, String req)
throws IOException {
HashMap<String, HashSet> permMap = gson.fromJson(req,
@ -166,6 +169,7 @@ public class NotebookRestApi {
*/
@PUT
@Path("interpreter/bind/{noteId}")
@ZeppelinApi
public Response bind(@PathParam("noteId") String noteId, String req) throws IOException {
List<String> settingIdList = gson.fromJson(req, new TypeToken<List<String>>(){}.getType());
notebook.bindInterpretersToNote(noteId, settingIdList);
@ -177,6 +181,7 @@ public class NotebookRestApi {
*/
@GET
@Path("interpreter/bind/{noteId}")
@ZeppelinApi
public Response bind(@PathParam("noteId") String noteId) {
List<InterpreterSettingListForNoteBind> settingList
= new LinkedList<InterpreterSettingListForNoteBind>();
@ -217,6 +222,7 @@ public class NotebookRestApi {
@GET
@Path("/")
@ZeppelinApi
public Response getNotebookList() throws IOException {
List<Map<String, String>> notesInfo = notebookServer.generateNotebooksInfo(false);
return new JsonResponse<>(Status.OK, "", notesInfo ).build();
@ -224,6 +230,7 @@ public class NotebookRestApi {
@GET
@Path("{notebookId}")
@ZeppelinApi
public Response getNotebook(@PathParam("notebookId") String notebookId) throws IOException {
Note note = notebook.getNote(notebookId);
if (note == null) {
@ -242,6 +249,7 @@ public class NotebookRestApi {
*/
@GET
@Path("export/{id}")
@ZeppelinApi
public Response exportNoteBook(@PathParam("id") String noteId) throws IOException {
String exportJson = notebook.exportNote(noteId);
return new JsonResponse(Status.OK, "", exportJson).build();
@ -256,6 +264,7 @@ public class NotebookRestApi {
*/
@POST
@Path("import")
@ZeppelinApi
public Response importNotebook(String req) throws IOException {
Note newNote = notebook.importNote(req, null);
return new JsonResponse<>(Status.CREATED, "", newNote.getId()).build();
@ -269,6 +278,7 @@ public class NotebookRestApi {
*/
@POST
@Path("/")
@ZeppelinApi
public Response createNote(String message) throws IOException {
LOG.info("Create new notebook by JSON {}" , message);
NewNotebookRequest request = gson.fromJson(message,
@ -302,6 +312,7 @@ public class NotebookRestApi {
*/
@DELETE
@Path("{notebookId}")
@ZeppelinApi
public Response deleteNote(@PathParam("notebookId") String notebookId) throws IOException {
LOG.info("Delete notebook {} ", notebookId);
if (!(notebookId.isEmpty())) {
@ -322,6 +333,7 @@ public class NotebookRestApi {
*/
@POST
@Path("{notebookId}")
@ZeppelinApi
public Response cloneNote(@PathParam("notebookId") String notebookId, String message) throws
IOException, CloneNotSupportedException, IllegalArgumentException {
LOG.info("clone notebook by JSON {}" , message);
@ -342,6 +354,7 @@ public class NotebookRestApi {
*/
@POST
@Path("{notebookId}/paragraph")
@ZeppelinApi
public Response insertParagraph(@PathParam("notebookId") String notebookId, String message)
throws IOException {
LOG.info("insert paragraph {} {}", notebookId, message);
@ -376,6 +389,7 @@ public class NotebookRestApi {
*/
@GET
@Path("{notebookId}/paragraph/{paragraphId}")
@ZeppelinApi
public Response getParagraph(@PathParam("notebookId") String notebookId,
@PathParam("paragraphId") String paragraphId) throws IOException {
LOG.info("get paragraph {} {}", notebookId, paragraphId);
@ -401,6 +415,7 @@ public class NotebookRestApi {
*/
@POST
@Path("{notebookId}/paragraph/{paragraphId}/move/{newIndex}")
@ZeppelinApi
public Response moveParagraph(@PathParam("notebookId") String notebookId,
@PathParam("paragraphId") String paragraphId,
@PathParam("newIndex") String newIndex) throws IOException {
@ -436,6 +451,7 @@ public class NotebookRestApi {
*/
@DELETE
@Path("{notebookId}/paragraph/{paragraphId}")
@ZeppelinApi
public Response deleteParagraph(@PathParam("notebookId") String notebookId,
@PathParam("paragraphId") String paragraphId) throws IOException {
LOG.info("delete paragraph {} {}", notebookId, paragraphId);
@ -465,6 +481,7 @@ public class NotebookRestApi {
*/
@POST
@Path("job/{notebookId}")
@ZeppelinApi
public Response runNoteJobs(@PathParam("notebookId") String notebookId) throws
IOException, IllegalArgumentException {
LOG.info("run notebook jobs {} ", notebookId);
@ -485,6 +502,7 @@ public class NotebookRestApi {
*/
@DELETE
@Path("job/{notebookId}")
@ZeppelinApi
public Response stopNoteJobs(@PathParam("notebookId") String notebookId) throws
IOException, IllegalArgumentException {
LOG.info("stop notebook jobs {} ", notebookId);
@ -509,6 +527,7 @@ public class NotebookRestApi {
*/
@GET
@Path("job/{notebookId}")
@ZeppelinApi
public Response getNoteJobStatus(@PathParam("notebookId") String notebookId) throws
IOException, IllegalArgumentException {
LOG.info("get notebook job status.");
@ -531,6 +550,7 @@ public class NotebookRestApi {
*/
@POST
@Path("job/{notebookId}/{paragraphId}")
@ZeppelinApi
public Response runParagraph(@PathParam("notebookId") String notebookId,
@PathParam("paragraphId") String paragraphId,
String message) throws
@ -570,6 +590,7 @@ public class NotebookRestApi {
*/
@DELETE
@Path("job/{notebookId}/{paragraphId}")
@ZeppelinApi
public Response stopParagraph(@PathParam("notebookId") String notebookId,
@PathParam("paragraphId") String paragraphId) throws
IOException, IllegalArgumentException {
@ -595,6 +616,7 @@ public class NotebookRestApi {
*/
@POST
@Path("cron/{notebookId}")
@ZeppelinApi
public Response registerCronJob(@PathParam("notebookId") String notebookId, String message) throws
IOException, IllegalArgumentException {
LOG.info("Register cron job note={} request cron msg={}", notebookId, message);
@ -627,6 +649,7 @@ public class NotebookRestApi {
*/
@DELETE
@Path("cron/{notebookId}")
@ZeppelinApi
public Response removeCronJob(@PathParam("notebookId") String notebookId) throws
IOException, IllegalArgumentException {
LOG.info("Remove cron job note {}", notebookId);
@ -652,6 +675,7 @@ public class NotebookRestApi {
*/
@GET
@Path("cron/{notebookId}")
@ZeppelinApi
public Response getCronJob(@PathParam("notebookId") String notebookId) throws
IOException, IllegalArgumentException {
LOG.info("Get cron job note {}", notebookId);
@ -669,6 +693,7 @@ public class NotebookRestApi {
*/
@GET
@Path("search")
@ZeppelinApi
public Response search(@QueryParam("q") String queryTerm) {
LOG.info("Searching notebooks for: {}", queryTerm);
String principal = SecurityUtils.getPrincipal();

View file

@ -17,6 +17,7 @@
package org.apache.zeppelin.rest;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.ticket.TicketContainer;
@ -58,6 +59,7 @@ public class SecurityRestApi {
*/
@GET
@Path("ticket")
@ZeppelinApi
public Response ticket() {
ZeppelinConfiguration conf = ZeppelinConfiguration.create();
String principal = SecurityUtils.getPrincipal();

View file

@ -17,6 +17,7 @@
package org.apache.zeppelin.rest;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.util.Util;
@ -47,6 +48,7 @@ public class ZeppelinRestApi {
@GET
@Path("version")
@ZeppelinApi
public Response getVersion() {
return new JsonResponse<>(Response.Status.OK, "Zeppelin version", Util.getVersion()).build();
}

View file

@ -44,6 +44,7 @@ import org.apache.zeppelin.scheduler.SchedulerFactory;
import org.apache.zeppelin.search.LuceneSearch;
import org.apache.zeppelin.search.SearchService;
import org.apache.zeppelin.socket.NotebookServer;
import org.apache.zeppelin.user.Credentials;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
@ -74,6 +75,7 @@ public class ZeppelinServer extends Application {
private NotebookRepo notebookRepo;
private SearchService notebookIndex;
private NotebookAuthorization notebookAuthorization;
private Credentials credentials;
private DependencyResolver depResolver;
public ZeppelinServer() throws Exception {
@ -90,9 +92,10 @@ public class ZeppelinServer extends Application {
this.notebookRepo = new NotebookRepoSync(conf);
this.notebookIndex = new LuceneSearch();
this.notebookAuthorization = new NotebookAuthorization(conf);
this.credentials = new Credentials(conf.credentialsPersist(), conf.getCredentialsPath());
notebook = new Notebook(conf,
notebookRepo, schedulerFactory, replFactory, notebookWsServer,
notebookIndex, notebookAuthorization);
notebookIndex, notebookAuthorization, credentials);
// to update notebook from application event from remote process.
heliumApplicationFactory.setNotebook(notebook);
@ -312,6 +315,9 @@ public class ZeppelinServer extends Application {
InterpreterRestApi interpreterApi = new InterpreterRestApi(replFactory);
singletons.add(interpreterApi);
CredentialRestApi credentialApi = new CredentialRestApi(credentials);
singletons.add(credentialApi);
SecurityRestApi securityApi = new SecurityRestApi();
singletons.add(securityApi);

View file

@ -200,13 +200,13 @@ public class ZeppelinIT extends AbstractZeppelinIT {
interpreterLink.click();
// add new dependency to spark interpreter
driver.findElement(By.xpath("//div[h3[text()[contains(.,'spark')]]]//button[contains(.,'edit')]")).sendKeys(Keys.ENTER);
driver.findElement(By.xpath("//div[@id='spark']//button[contains(.,'edit')]")).sendKeys(Keys.ENTER);
WebElement depArtifact = pollingWait(By.xpath("//input[@ng-model='setting.depArtifact']"),
MAX_BROWSER_TIMEOUT_SEC);
String artifact = "org.apache.commons:commons-csv:1.1";
depArtifact.sendKeys(artifact);
driver.findElement(By.xpath("//div[contains(@class,'box')][contains(.,'%spark')]//form//button[1]")).click();
driver.findElement(By.xpath("//div[@id='spark']//form//button[1]")).click();
driver.findElement(By.xpath("//div[@class='modal-dialog'][contains(.,'Do you want to update this interpreter and restart with new settings?')]" +
"//div[@class='modal-footer']//button[contains(.,'OK')]")).click();
@ -236,11 +236,11 @@ public class ZeppelinIT extends AbstractZeppelinIT {
// reset dependency
interpreterLink.click();
driver.findElement(By.xpath("//div[h3[text()[contains(.,'spark')]]]//button[contains(.,'edit')]")).sendKeys(Keys.ENTER);
driver.findElement(By.xpath("//div[@id='spark']//button[contains(.,'edit')]")).sendKeys(Keys.ENTER);
WebElement testDepRemoveBtn = pollingWait(By.xpath("//tr[descendant::text()[contains(.,'" +
artifact + "')]]/td[3]/div"), MAX_IMPLICIT_WAIT);
testDepRemoveBtn.click();
driver.findElement(By.xpath("//div[contains(@class,'box')][contains(.,'%spark')]//form//button[1]")).click();
artifact + "')]]/td[3]/button"), MAX_IMPLICIT_WAIT);
testDepRemoveBtn.sendKeys(Keys.ENTER);
driver.findElement(By.xpath("//div[@id='spark']//form//button[1]")).click();
driver.findElement(By.xpath("//div[@class='modal-dialog'][contains(.,'Do you want to update this interpreter and restart with new settings?')]" +
"//div[@class='modal-footer']//button[contains(.,'OK')]")).click();
} catch (Exception e) {

View file

@ -22,14 +22,14 @@
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-web</artifactId>
<packaging>war</packaging>
<version>0.6.0-incubating-SNAPSHOT</version>
<version>0.6.0-SNAPSHOT</version>
<name>Zeppelin: web Application</name>
<!-- See https://github.com/eirslett/frontend-maven-plugin/issues/229 -->

View file

@ -66,6 +66,10 @@
templateUrl: 'app/interpreter/interpreter.html',
controller: 'InterpreterCtrl'
})
.when('/credential', {
templateUrl: 'app/credential/credential.html',
controller: 'CredentialCtrl'
})
.when('/configuration', {
templateUrl: 'app/configuration/configuration.html',
controller: 'ConfigurationCtrl'

View file

@ -0,0 +1,40 @@
/* jshint loopfunc: true */
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
'use strict';
angular.module('zeppelinWebApp').controller('CredentialCtrl', function($scope, $route, $routeParams, $location, $rootScope,
$http, baseUrlSrv) {
$scope._ = _;
$scope.updateCredentials = function() {
$http.put(baseUrlSrv.getRestApiBase() + '/credential',
{ 'entity': $scope.credentialEntity,
'username': $scope.credentialUsername,
'password': $scope.credentialPassword
} ).
success(function (data, status, headers, config) {
alert('Successfully saved credentials');
$scope.credentialEntity = '';
$scope.credentialUsername = '';
$scope.credentialPassword = '';
console.log('Success %o %o', status, data.message);
}).
error(function (data, status, headers, config) {
alert('Error saving credentials');
console.log('Error %o %o', status, data.message);
});
};
});

View file

@ -0,0 +1,86 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
.interpreterHead {
margin: -10px -10px 20px;
padding: 10px 15px 15px 15px;
background: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
border-bottom: 1px solid #E5E5E5;
}
.interpreterHead .header {
font-family: 'Roboto', sans-serif;
}
.interpreterHead textarea,
.interpreter textarea {
width: 100%;
display: block;
height: 20px;
resize: none;
border: 1px solid #CCCCCC;
font-size: 12px;
}
.interpreter .interpreter-title {
font-size: 20px;
font-weight: bold;
color: #3071a9;
float: left;
margin-top: 0;
}
.interpreter ul {
margin: 0;
padding: 0;
}
.interpreter .interpreterInfo {
list-style-type: none;
}
.interpreter table tr .interpreterPropertyKey {
padding : 5px 5px 5px 5px;
}
.interpreter table tr .interpreterPropertyValue {
padding : 5px 5px 5px 5px;
display: block;
max-height: 100px;
overflow-y: auto;
}
.interpreterSettingAdd {
margin : 5px 5px 5px 5px;
padding : 10px 10px 10px 10px;
}
.editable-wrap {
width : 100%;
}
.interpreter h5 {
font-weight: bold;
}
.new_h3 {
margin-top: 1px;
padding-top: 7px;
float: left;
}
.empty-properties-message {
color: #666;
}

View file

@ -0,0 +1,71 @@
<!--
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<div class="interpreterHead">
<div class="header">
<div class="row">
<div class="col-md-12">
<h3 class="new_h3">
Credentials
</h3>
</div>
</div>
<div class="row">
<div class="col-md-12">
Add credentials for entities one at a time.<br>
</div>
</div>
</div>
</div>
<div class="box width-full home"
>
<div>
<div class="row interpreter">
<div class="col-md-12">
<table class="table table-striped">
<thead>
<tr>
<th style="width:30%">Entity</th>
<th>Username</th>
<th>Password</th>
<th ng-if="valueform.$visible">action</th>
</tr>
</thead>
<tr>
<td>
<textarea msd-elastic ng-model="credentialEntity"></textarea>
</td>
<td>
<textarea msd-elastic ng-model="credentialUsername"></textarea>
</td>
<td>
<input type="password" ng-model="credentialPassword"/>
</td>
</tr>
</table>
<form editable-form name="valueform" onaftersave="updateCredentials()">
<button type="submit" class="btn btn-primary"
ng-disabled="valueform.$waiting">
Save
</button>
<button type="button" class="btn btn-default"
ng-disabled="valueform.$waiting"
ng-click="valueform.$cancel()">
Cancel
</button>
</form>
</div>
</div>
</div>
</div>

View file

@ -78,12 +78,12 @@ limitations under the License.
<div class="col-md-6">
<h4>Help</h4>
Get started with <a style="text-decoration: none;" target="_blank"
href="http://zeppelin.incubator.apache.org/docs/latest/index.html">Zeppelin documentation</a><br>
href="http://zeppelin.apache.org/docs/latest/index.html">Zeppelin documentation</a><br>
<h4>Community</h4>
Please feel free to help us to improve Zeppelin, <br>
Any contribution are welcome!<br><br>
<a style="text-decoration: none;" href="http://zeppelin.incubator.apache.org/community.html"
<a style="text-decoration: none;" href="http://zeppelin.apache.org/community.html"
target="_blank"><i style="font-size: 15px;" class="fa fa-users"></i> Mailing list</a><br>
<a style="text-decoration: none;" href="https://issues.apache.org/jira/browse/ZEPPELIN"
target="_blank"><i style="font-size: 15px;" class="fa fa-bug"></i> Issues tracking</a><br>

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