mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
Merge remote-tracking branch 'origin/master' into livyInterperter
This commit is contained in:
commit
5c2bf139ae
10 changed files with 86 additions and 35 deletions
44
README.md
44
README.md
|
|
@ -18,10 +18,11 @@ Core feature:
|
|||
To know more about Zeppelin, visit our web site [http://zeppelin.incubator.apache.org](http://zeppelin.incubator.apache.org)
|
||||
|
||||
## Requirements
|
||||
* Git
|
||||
* Java 1.7
|
||||
* Tested on Mac OSX, Ubuntu 14.X, CentOS 6.X
|
||||
* Tested on Mac OSX, Ubuntu 14.X, CentOS 6.X, Windows 7 Pro SP1
|
||||
* Maven (if you want to build from the source code)
|
||||
* Node.js Package Manager (npm)
|
||||
* Node.js Package Manager (npm, downloaded by Maven during build phase)
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
|
@ -29,14 +30,49 @@ To know more about Zeppelin, visit our web site [http://zeppelin.incubator.apach
|
|||
If you don't have requirements prepared, install it.
|
||||
(The installation method may vary according to your environment, example is for Ubuntu.)
|
||||
|
||||
```sh
|
||||
```
|
||||
sudo apt-get update
|
||||
sudo apt-get install git
|
||||
sudo apt-get install openjdk-7-jdk
|
||||
sudo apt-get install npm
|
||||
sudo apt-get install libfontconfig
|
||||
```
|
||||
|
||||
# install maven
|
||||
#### Proxy settings (optional)
|
||||
If you are behind a corporate Proxy with NTLM authentication you can use [Cntlm Authentication Proxy](http://cntlm.sourceforge.net/) .
|
||||
|
||||
Before build start, run these commands from shell.
|
||||
```
|
||||
export http_proxy=http://localhost:3128
|
||||
export https_proxy=http://localhost:3128
|
||||
export HTTP_PROXY=http://localhost:3128
|
||||
export HTTPS_PROXY=http://localhost:3128
|
||||
npm config set proxy http://localhost:3128
|
||||
npm config set https-proxy http://localhost:3128
|
||||
npm config set registry "http://registry.npmjs.org/"
|
||||
npm config set strict-ssl false
|
||||
npm cache clean
|
||||
git config --global http.proxy http://localhost:3128
|
||||
git config --global https.proxy http://localhost:3128
|
||||
git config --global url."http://".insteadOf git://
|
||||
```
|
||||
|
||||
After build is complete, run these commands to cleanup.
|
||||
```
|
||||
npm config rm proxy
|
||||
npm config rm https-proxy
|
||||
git config --global --unset http.proxy
|
||||
git config --global --unset https.proxy
|
||||
git config --global --unset url."http://".insteadOf
|
||||
```
|
||||
|
||||
_Notes:_
|
||||
- If you are on Windows replace `export` with `set` to set env variables
|
||||
- Replace `localhost:3128` with standard pattern `http://user:pwd@host:port`
|
||||
- Git configuration is needed because Bower use it for fetching from GitHub
|
||||
|
||||
#### Install maven
|
||||
```
|
||||
wget http://www.eu.apache.org/dist/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz
|
||||
sudo tar -zxf apache-maven-3.3.3-bin.tar.gz -C /usr/local/
|
||||
sudo ln -s /usr/local/apache-maven-3.3.3/bin/mvn /usr/local/bin/mvn
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 202 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 155 KiB |
|
|
@ -34,11 +34,12 @@ This instruction based on Ubuntu 14.04 LTS but may work with other OS with few c
|
|||
|
||||
1. Install NGINX server on your server instance
|
||||
|
||||
You can install NGINX server with same machine where zeppelin installed or separate machine where it is dedicated to serve as proxy server.
|
||||
You can install NGINX server with same box where zeppelin installed or separate box where it is dedicated to serve as proxy server.
|
||||
|
||||
```
|
||||
$ apt-get install nginx
|
||||
```
|
||||
*Important: On pre 1.3.13 version of NGINX, Proxy for Websocket may not fully works. Please use latest version of NGINX. See: [NGINX documentation](https://www.nginx.com/blog/websocket-nginx/)*
|
||||
|
||||
1. Setup init script in NGINX
|
||||
|
||||
|
|
@ -46,30 +47,30 @@ This instruction based on Ubuntu 14.04 LTS but may work with other OS with few c
|
|||
|
||||
```
|
||||
$ cd /etc/nginx/sites-available
|
||||
$ touch my-basic-auth
|
||||
$ touch my-zeppelin-auth-setting
|
||||
```
|
||||
|
||||
Now add this script into `my-basic-auth` file. You can comment out `optional` lines If you want serve Zeppelin under regular HTTP 80 Port.
|
||||
Now add this script into `my-zeppelin-auth-setting` file. You can comment out `optional` lines If you want serve Zeppelin under regular HTTP 80 Port.
|
||||
|
||||
```
|
||||
upstream zeppelin {
|
||||
server [YOUR-ZEPPELIN-SERVER-IP]:8080;
|
||||
server [YOUR-ZEPPELIN-SERVER-IP]:[YOUR-ZEPPELIN-SERVER-PORT]; # For security, It is highly recommended to make this address/port as non-public accessible
|
||||
}
|
||||
|
||||
# Zeppelin Website
|
||||
server {
|
||||
listen [YOUR-ZEPPELIN-WEB-SERVER-PORT];
|
||||
listen 443 ssl; # optional, to serve HTTPS connection
|
||||
server_name [YOUR-ZEPPELIN-SERVER-HOST]; # for example: zeppelin.mycompany.com
|
||||
listen 443 ssl; # optional, to serve HTTPS connection
|
||||
server_name [YOUR-ZEPPELIN-SERVER-HOST]; # for example: zeppelin.mycompany.com
|
||||
|
||||
ssl_certificate [PATH-TO-YOUR-CERT-FILE]; # optional, to serve HTTPS connection
|
||||
ssl_certificate_key [PATH-TO-YOUR-CERT-KEY-FILE]; # optional, to serve HTTPS connection
|
||||
|
||||
if ($ssl_protocol = "") {
|
||||
rewrite ^ https://$host$request_uri? permanent; # optional, force to use HTTPS
|
||||
rewrite ^ https://$host$request_uri? permanent; # optional, to force use of HTTPS
|
||||
}
|
||||
|
||||
location / {
|
||||
location / { # For regular websever support
|
||||
proxy_pass http://zeppelin;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
|
@ -80,7 +81,7 @@ This instruction based on Ubuntu 14.04 LTS but may work with other OS with few c
|
|||
auth_basic_user_file /etc/nginx/.htpasswd;
|
||||
}
|
||||
|
||||
location /ws {
|
||||
location /ws { # For websocket support
|
||||
proxy_pass http://zeppelin;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade websocket;
|
||||
|
|
@ -93,7 +94,7 @@ This instruction based on Ubuntu 14.04 LTS but may work with other OS with few c
|
|||
Then make a symbolic link to this file from `/etc/nginx/sites-enabled/` to enable configuration above when NGINX reloads.
|
||||
|
||||
```
|
||||
$ ln -s /etc/nginx/sites-enabled/my-basic-auth /etc/nginx/sites-available/my-basic-auth
|
||||
$ ln -s /etc/nginx/sites-enabled/my-zeppelin-auth-setting /etc/nginx/sites-available/my-zeppelin-auth-setting
|
||||
```
|
||||
|
||||
1. Setup user credential into `.htpasswd` file and restart server
|
||||
|
|
@ -102,11 +103,11 @@ This instruction based on Ubuntu 14.04 LTS but may work with other OS with few c
|
|||
|
||||
```
|
||||
$ cd /etc/nginx
|
||||
$ htpasswd -c htpasswd [YOUR_ID]
|
||||
$ NEW passwd: [YOUR_PASSWORD]
|
||||
$ RE-type new passwd: [YOUR_PASSWORD_AGAIN]
|
||||
$ htpasswd -c htpasswd [YOUR-ID]
|
||||
$ NEW passwd: [YOUR-PASSWORD]
|
||||
$ RE-type new passwd: [YOUR-PASSWORD-AGAIN]
|
||||
```
|
||||
Or you can use your own apache `.htpasswd` files in other location by setup property `auth_basic_user_file`
|
||||
Or you can use your own apache `.htpasswd` files in other location for setting up property: `auth_basic_user_file`
|
||||
|
||||
Restart NGINX server.
|
||||
|
||||
|
|
@ -115,9 +116,6 @@ This instruction based on Ubuntu 14.04 LTS but may work with other OS with few c
|
|||
```
|
||||
Then check HTTP Basic Authentication works in browser. If you can see regular basic auth popup and then able to login with credential you entered into `.htpasswd` you are good to go.
|
||||
|
||||
<img src="/assets/themes/zeppelin/img/screenshots/authentication-basic-auth-nginx-request.png" />
|
||||
<img src="/assets/themes/zeppelin/img/screenshots/authentication-basic-auth-nginx-https.png" />
|
||||
|
||||
1. More security consideration
|
||||
|
||||
* Using HTTPS connection with Basic Authentication is highly recommended since basic auth without encryption may expose your important credential information over the network.
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ import org.apache.commons.io.IOUtils;
|
|||
import org.apache.zeppelin.interpreter.InterpreterException;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOutput;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOutputListener;
|
||||
import parquet.org.slf4j.Logger;
|
||||
import parquet.org.slf4j.LoggerFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Collections;
|
||||
|
|
|
|||
|
|
@ -399,14 +399,17 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
broadcastAll(new Message(OP.NOTES_INFO).put("notes", notesInfo));
|
||||
}
|
||||
|
||||
void permissionError(NotebookSocket conn, String op, Set<String> current,
|
||||
Set<String> allowed) throws IOException {
|
||||
void permissionError(NotebookSocket conn, String op, Set<String> userAndRoles,
|
||||
Set<String> allowed) throws IOException {
|
||||
LOG.info("Cannot {}. Connection readers {}. Allowed readers {}",
|
||||
op, current, allowed);
|
||||
op, userAndRoles, allowed);
|
||||
|
||||
String userName = userAndRoles.iterator().next();
|
||||
|
||||
conn.send(serializeMessage(new Message(OP.AUTH_INFO).put("info",
|
||||
"Insufficient privileges to " + op + " note.\n\n" +
|
||||
"Insufficient privileges to " + op + " notebook.\n\n" +
|
||||
"Allowed users or roles: " + allowed.toString() + "\n\n" +
|
||||
"User belongs to: " + current.toString())));
|
||||
"But the user " + userName + " belongs to: " + userAndRoles.toString())));
|
||||
}
|
||||
|
||||
private void sendNote(NotebookSocket conn, HashSet<String> userAndRoles, Notebook notebook,
|
||||
|
|
@ -1009,6 +1012,7 @@ public class NotebookServer extends WebSocketServlet implements
|
|||
new InterpreterResult(InterpreterResult.Code.ERROR, ex.getMessage()),
|
||||
ex);
|
||||
p.setStatus(Status.ERROR);
|
||||
broadcast(note.id(), new Message(OP.PARAGRAPH).put("paragraph", p));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,7 +364,9 @@ angular.module('zeppelinWebApp')
|
|||
var newType = $scope.getResultType(data.paragraph);
|
||||
var oldGraphMode = $scope.getGraphMode();
|
||||
var newGraphMode = $scope.getGraphMode(data.paragraph);
|
||||
var resultRefreshed = (data.paragraph.dateFinished !== $scope.paragraph.dateFinished) || isEmpty(data.paragraph.result) !== isEmpty($scope.paragraph.result);
|
||||
var resultRefreshed = (data.paragraph.dateFinished !== $scope.paragraph.dateFinished) ||
|
||||
isEmpty(data.paragraph.result) !== isEmpty($scope.paragraph.result) ||
|
||||
data.paragraph.status === 'ERROR';
|
||||
|
||||
var statusChanged = (data.paragraph.status !== $scope.paragraph.status);
|
||||
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ table.dataTable.table-condensed .sorting_desc:after {
|
|||
|
||||
.tableDisplay .option .columns ul {
|
||||
background: white;
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
padding: 3px 3px 3px 3px;
|
||||
height: 150px;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ angular.module('zeppelinWebApp').factory('notebookListDataFactory', function() {
|
|||
notes.root = {children: []};
|
||||
_.reduce(notesList, function(root, note) {
|
||||
var noteName = note.name || note.id;
|
||||
var nodes = noteName.match(/([^\\\][^\/]|\\\/)+/g);
|
||||
var nodes = noteName.match(/([^\/][^\/]*)/g);
|
||||
|
||||
// recursively add nodes
|
||||
addNode(root, nodes, note.id);
|
||||
|
|
|
|||
|
|
@ -16,17 +16,18 @@ describe('Factory: NotebookList', function() {
|
|||
var notesList = [
|
||||
{name: 'A', id: '000001'},
|
||||
{name: 'B', id: '000002'},
|
||||
{id: '000003'}, // notebook without name
|
||||
{id: '000003'}, // notebook without name
|
||||
{name: '/C/CA', id: '000004'},
|
||||
{name: '/C/CB', id: '000005'},
|
||||
{name: '/C/CB/CBA', id: '000006'}, // same name with a dir
|
||||
{name: '/C/CB/CBA', id: '000007'}, // same name with another note
|
||||
{name: 'C///CB//CBB', id: '000008'}
|
||||
{name: '/C/CB/CBA', id: '000007'}, // same name with another note
|
||||
{name: 'C///CB//CBB', id: '000008'},
|
||||
{name: 'D/D[A/DA]B', id:'000009'} // check if '[' and ']' considered as folder seperator
|
||||
];
|
||||
notebookList.setNotes(notesList);
|
||||
|
||||
var flatList = notebookList.flatList;
|
||||
expect(flatList.length).toBe(8);
|
||||
expect(flatList.length).toBe(9);
|
||||
expect(flatList[0].name).toBe('A');
|
||||
expect(flatList[0].id).toBe('000001');
|
||||
expect(flatList[1].name).toBe('B');
|
||||
|
|
@ -36,9 +37,10 @@ describe('Factory: NotebookList', function() {
|
|||
expect(flatList[5].name).toBe('/C/CB/CBA');
|
||||
expect(flatList[6].name).toBe('/C/CB/CBA');
|
||||
expect(flatList[7].name).toBe('C///CB//CBB');
|
||||
expect(flatList[8].name).toBe('D/D[A/DA]B');
|
||||
|
||||
var folderList = notebookList.root.children;
|
||||
expect(folderList.length).toBe(4);
|
||||
expect(folderList.length).toBe(5);
|
||||
expect(folderList[0].name).toBe('A');
|
||||
expect(folderList[0].id).toBe('000001');
|
||||
expect(folderList[1].name).toBe('B');
|
||||
|
|
@ -64,6 +66,14 @@ describe('Factory: NotebookList', function() {
|
|||
expect(folderList[3].children[2].children[2].name).toBe('CBB');
|
||||
expect(folderList[3].children[2].children[2].id).toBe('000008');
|
||||
expect(folderList[3].children[2].children[2].children).toBeUndefined();
|
||||
expect(folderList[4].name).toBe('D');
|
||||
expect(folderList[4].id).toBeUndefined();
|
||||
expect(folderList[4].children.length).toBe(1);
|
||||
expect(folderList[4].children[0].name).toBe('D[A');
|
||||
expect(folderList[4].children[0].id).toBeUndefined();
|
||||
expect(folderList[4].children[0].children[0].name).toBe('DA]B');
|
||||
expect(folderList[4].children[0].children[0].id).toBe('000009');
|
||||
expect(folderList[4].children[0].children[0].children).toBeUndefined();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue