Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
efe4c34
Add new Rest api endpoint for notebook Repo settings
anthonycorbacho Oct 23, 2016
a4d9749
Added utility class for notebook re po payload deserialization
anthonycorbacho Oct 23, 2016
f7c7bf2
Update method :: updateRepoSettings to create NotebookRepoSettingsReq…
anthonycorbacho Oct 23, 2016
30d29cd
Update zeppelin server and add NotebookRepo rest api to the singleton
anthonycorbacho Oct 23, 2016
054d2aa
Base structure for notebook repo ui
corneadoug Oct 11, 2016
8075b04
Render mocked list of notebook repo settings
corneadoug Oct 11, 2016
76479b3
Change presentation of notebook settings
corneadoug Oct 12, 2016
6a97512
Get Repos from api
corneadoug Oct 12, 2016
9c1f999
Implement edit
corneadoug Oct 16, 2016
05a64de
Improve edit repo
corneadoug Oct 16, 2016
4d745ab
Improve ux
corneadoug Oct 16, 2016
23912ce
Added new wrapper class
anthonycorbacho Oct 23, 2016
53346d7
Add new methods in notebookRepo :: get and set settings in notebook
anthonycorbacho Oct 23, 2016
8e890d3
Add new wrapper for notebook repo PLUS settings
anthonycorbacho Oct 23, 2016
5a13e62
Added 2 new methos in notebookRepoSync, exposed get and update notebo…
anthonycorbacho Oct 23, 2016
2d67bc8
Added method from notebook repo interface
anthonycorbacho Oct 23, 2016
0b4b74a
Add exemple of how to change local notebook repo FS
anthonycorbacho Oct 23, 2016
dc7fc50
Fix indentation
anthonycorbacho Oct 24, 2016
517ebc8
Fix style
anthonycorbacho Oct 24, 2016
d49bfe1
Fix style
anthonycorbacho Oct 24, 2016
357b659
Fix ASF header
anthonycorbacho Oct 24, 2016
7fc1f37
Change textarea size to 100 row
anthonycorbacho Oct 24, 2016
42fd3b5
Apply broadcasting note list after sucessful update for notebook repo
anthonycorbacho Oct 24, 2016
23ad18e
Rename NotebookRepoSettings to NotebookRepoSettingsInfo
anthonycorbacho Oct 24, 2016
6f17b18
Add tests :: API and REST API
anthonycorbacho Oct 25, 2016
6d63832
Fix style and rebase mistake...
anthonycorbacho Oct 25, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* 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 java.util.Collections;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.apache.commons.lang.StringUtils;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.notebook.repo.NotebookRepoSync;
import org.apache.zeppelin.notebook.repo.NotebookRepoWithSettings;
import org.apache.zeppelin.rest.message.NotebookRepoSettingsRequest;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.socket.NotebookServer;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.apache.zeppelin.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;

/**
* NoteRepo rest API endpoint.
*
*/
@Path("/notebook-repositories")
@Produces("application/json")
public class NotebookRepoRestApi {

private static final Logger LOG = LoggerFactory.getLogger(NotebookRepoRestApi.class);

private Gson gson = new Gson();
private NotebookRepoSync noteRepos;
private NotebookServer notebookWsServer;

public NotebookRepoRestApi() {}

public NotebookRepoRestApi(NotebookRepoSync noteRepos, NotebookServer notebookWsServer) {
this.noteRepos = noteRepos;
this.notebookWsServer = notebookWsServer;
}

/**
* List all notebook repository
*/
@GET
@ZeppelinApi
public Response listRepoSettings() {
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
LOG.info("Getting list of NoteRepo with Settings for user {}", subject.getUser());
List<NotebookRepoWithSettings> settings = noteRepos.getNotebookRepos(subject);
return new JsonResponse<>(Status.OK, "", settings).build();
}

/**
* Update a specific note repo.
*
* @param message
* @param settingId
* @return
*/
@PUT
@ZeppelinApi
public Response updateRepoSetting(String payload) {
if (StringUtils.isBlank(payload)) {
return new JsonResponse<>(Status.NOT_FOUND, "", Collections.emptyMap()).build();
}
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
NotebookRepoSettingsRequest newSettings = NotebookRepoSettingsRequest.EMPTY;
try {
newSettings = gson.fromJson(payload, NotebookRepoSettingsRequest.class);
} catch (JsonSyntaxException e) {
LOG.error("Cannot update notebook repo settings", e);
return new JsonResponse<>(Status.NOT_ACCEPTABLE, "",
ImmutableMap.of("error", "Invalid payload structure")).build();
}

if (NotebookRepoSettingsRequest.isEmpty(newSettings)) {
LOG.error("Invalid property");
return new JsonResponse<>(Status.NOT_ACCEPTABLE, "",
ImmutableMap.of("error", "Invalid payload")).build();
}
LOG.info("User {} is going to change repo setting", subject.getUser());
NotebookRepoWithSettings updatedSettings =
noteRepos.updateNotebookRepo(newSettings.name, newSettings.settings, subject);
if (!updatedSettings.isEmpty()) {
LOG.info("Broadcasting note list to user {}", subject.getUser());
notebookWsServer.broadcastReloadedNoteList(subject, null);
}
return new JsonResponse<>(Status.OK, "", updatedSettings).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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.message;

import java.util.Collections;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

/**
* Represent payload of a notebook repo settings.
*/
public class NotebookRepoSettingsRequest {

public static final NotebookRepoSettingsRequest EMPTY = new NotebookRepoSettingsRequest();

public String name;
public Map<String, String> settings;

public NotebookRepoSettingsRequest() {
name = StringUtils.EMPTY;
settings = Collections.emptyMap();
}

public boolean isEmpty() {
return this == EMPTY;
}

public static boolean isEmpty(NotebookRepoSettingsRequest repoSetting) {
if (repoSetting == null) {
return true;
}
return repoSetting.isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;

import javax.net.ssl.SSLContext;
import javax.servlet.DispatcherType;
import javax.ws.rs.core.Application;

Expand All @@ -37,17 +35,29 @@
import org.apache.zeppelin.interpreter.InterpreterFactory;
import org.apache.zeppelin.notebook.Notebook;
import org.apache.zeppelin.notebook.NotebookAuthorization;
import org.apache.zeppelin.notebook.repo.NotebookRepo;
import org.apache.zeppelin.notebook.repo.NotebookRepoSync;
import org.apache.zeppelin.rest.*;
import org.apache.zeppelin.rest.ConfigurationsRestApi;
import org.apache.zeppelin.rest.CredentialRestApi;
import org.apache.zeppelin.rest.HeliumRestApi;
import org.apache.zeppelin.rest.InterpreterRestApi;
import org.apache.zeppelin.rest.LoginRestApi;
import org.apache.zeppelin.rest.NotebookRepoRestApi;
import org.apache.zeppelin.rest.NotebookRestApi;
import org.apache.zeppelin.rest.SecurityRestApi;
import org.apache.zeppelin.rest.ZeppelinRestApi;
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.apache.zeppelin.utils.SecurityUtils;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.DefaultServlet;
Expand All @@ -73,8 +83,8 @@ public class ZeppelinServer extends Application {

private SchedulerFactory schedulerFactory;
private InterpreterFactory replFactory;
private NotebookRepo notebookRepo;
private SearchService noteSearchService;
private NotebookRepoSync notebookRepo;
private NotebookAuthorization notebookAuthorization;
private Credentials credentials;
private DependencyResolver depResolver;
Expand Down Expand Up @@ -308,6 +318,9 @@ public Set<Object> getSingletons() {
= new NotebookRestApi(notebook, notebookWsServer, noteSearchService);
singletons.add(notebookApi);

NotebookRepoRestApi notebookRepoApi = new NotebookRepoRestApi(notebookRepo, notebookWsServer);
singletons.add(notebookRepoApi);

HeliumRestApi heliumApi = new HeliumRestApi(helium, heliumApplicationFactory, notebook);
singletons.add(heliumApi);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* 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 static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertThat;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.commons.lang.StringUtils;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

/**
* NotebookRepo rest api test.
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class NotebookRepoRestApiTest extends AbstractTestRestApi {

Gson gson = new Gson();
AuthenticationInfo anonymous;

@BeforeClass
public static void init() throws Exception {
AbstractTestRestApi.startUp();
}

@AfterClass
public static void destroy() throws Exception {
AbstractTestRestApi.shutDown();
}

@Before
public void setUp() {
anonymous = new AuthenticationInfo("anonymous");
}

private List<Map<String, Object>> getListOfReposotiry() throws IOException {
GetMethod get = httpGet("/notebook-repositories");
Map<String, Object> responce = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String, Object>>() {}.getType());
get.releaseConnection();
return (List<Map<String, Object>>) responce.get("body");
}

private void updateNotebookRepoWithNewSetting(String payload) throws IOException {
PutMethod put = httpPut("/notebook-repositories", payload);
int status = put.getStatusCode();
put.releaseConnection();
assertThat(status, is(200));
}

@Test public void ThatCanGetNotebookRepositoiesSettings() throws IOException {
List<Map<String, Object>> listOfRepositories = getListOfReposotiry();
assertThat(listOfRepositories.size(), is(not(0)));
}

@Test public void setNewDirectoryForLocalDirectory() throws IOException {
List<Map<String, Object>> listOfRepositories = getListOfReposotiry();
String localVfs = StringUtils.EMPTY;
String className = StringUtils.EMPTY;

for (int i = 0; i < listOfRepositories.size(); i++) {
if (listOfRepositories.get(i).get("name").equals("VFSNotebookRepo")) {
localVfs = (String) ((List<Map<String, Object>>)listOfRepositories.get(i).get("settings")).get(0).get("selected");
className = (String) listOfRepositories.get(i).get("className");
break;
}
}

if (StringUtils.isBlank(localVfs)) {
// no loval VFS set...
return;
}

String payload = "{ \"name\": \"" + className + "\", \"settings\" : { \"Notebook Path\" : \"/tmp/newDir\" } }";
updateNotebookRepoWithNewSetting(payload);

// Verify
listOfRepositories = getListOfReposotiry();
String updatedPath = StringUtils.EMPTY;
for (int i = 0; i < listOfRepositories.size(); i++) {
if (listOfRepositories.get(i).get("name").equals("VFSNotebookRepo")) {
updatedPath = (String) ((List<Map<String, Object>>)listOfRepositories.get(i).get("settings")).get(0).get("selected");
break;
}
}
assertThat(updatedPath, is("/tmp/newDir"));

// go back to normal
payload = "{ \"name\": \"" + className + "\", \"settings\" : { \"Notebook Path\" : \"" + localVfs + "\" } }";
updateNotebookRepoWithNewSetting(payload);
}
}
5 changes: 5 additions & 0 deletions zeppelin-web/src/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
templateUrl: 'app/interpreter/interpreter.html',
controller: 'InterpreterCtrl'
})
.when('/notebookRepos', {
templateUrl: 'app/notebookRepos/notebookRepos.html',
controller: 'NotebookReposCtrl',
controllerAs: 'noterepo'
})
.when('/credential', {
templateUrl: 'app/credential/credential.html',
controller: 'CredentialCtrl'
Expand Down
Loading