mirror of
https://github.com/apache/zeppelin
synced 2026-05-24 09:38:26 +00:00
* Fix DependencyResolver addRepo/delRepo method
* Manage repository information in `conf/interpreter.json` * Front-end modification to manage repository list * Add RestApi for adding/deleting repository * Fix tests
This commit is contained in:
parent
fe9cb92f57
commit
bae0c02f11
16 changed files with 343 additions and 39 deletions
|
|
@ -26,6 +26,7 @@ import org.sonatype.aether.RepositorySystem;
|
|||
import org.sonatype.aether.RepositorySystemSession;
|
||||
import org.sonatype.aether.repository.Authentication;
|
||||
import org.sonatype.aether.repository.RemoteRepository;
|
||||
import org.sonatype.aether.repository.RepositoryPolicy;
|
||||
import org.sonatype.aether.resolution.ArtifactResult;
|
||||
|
||||
/**
|
||||
|
|
@ -42,12 +43,19 @@ public abstract class AbstractDependencyResolver {
|
|||
repos.add(Booter.newCentralRepository()); // add maven central
|
||||
repos.add(Booter.newLocalRepository());
|
||||
}
|
||||
|
||||
public List<RemoteRepository> getRepos() {
|
||||
return this.repos;
|
||||
}
|
||||
|
||||
public void addRepo(String id, String url, boolean snapshot) {
|
||||
synchronized (repos) {
|
||||
delRepo(id);
|
||||
RemoteRepository rr = new RemoteRepository(id, "default", url);
|
||||
rr.setPolicy(snapshot, null);
|
||||
rr.setPolicy(true, new RepositoryPolicy(
|
||||
snapshot,
|
||||
RepositoryPolicy.UPDATE_POLICY_DAILY,
|
||||
RepositoryPolicy.CHECKSUM_POLICY_WARN));
|
||||
repos.add(rr);
|
||||
}
|
||||
}
|
||||
|
|
@ -56,7 +64,10 @@ public abstract class AbstractDependencyResolver {
|
|||
synchronized (repos) {
|
||||
delRepo(id);
|
||||
RemoteRepository rr = new RemoteRepository(id, "default", url);
|
||||
rr.setPolicy(snapshot, null);
|
||||
rr.setPolicy(true, new RepositoryPolicy(
|
||||
snapshot,
|
||||
RepositoryPolicy.UPDATE_POLICY_DAILY,
|
||||
RepositoryPolicy.CHECKSUM_POLICY_WARN));
|
||||
rr.setAuthentication(auth);
|
||||
repos.add(rr);
|
||||
}
|
||||
|
|
@ -65,7 +76,7 @@ public abstract class AbstractDependencyResolver {
|
|||
public RemoteRepository delRepo(String id) {
|
||||
synchronized (repos) {
|
||||
Iterator<RemoteRepository> it = repos.iterator();
|
||||
if (it.hasNext()) {
|
||||
while (it.hasNext()) {
|
||||
RemoteRepository repo = it.next();
|
||||
if (repo.getId().equals(id)) {
|
||||
it.remove();
|
||||
|
|
|
|||
|
|
@ -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.dep.Repository;
|
||||
import org.apache.zeppelin.interpreter.*;
|
||||
import org.apache.zeppelin.interpreter.Interpreter.RegisteredInterpreter;
|
||||
import org.apache.zeppelin.rest.message.NewInterpreterSettingRequest;
|
||||
|
|
@ -43,6 +44,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import org.sonatype.aether.RepositoryException;
|
||||
import org.sonatype.aether.repository.RemoteRepository;
|
||||
|
||||
/**
|
||||
* Interpreter Rest API
|
||||
|
|
@ -99,7 +101,7 @@ public class InterpreterRestApi {
|
|||
new InterpreterOption(true),
|
||||
p);
|
||||
InterpreterSetting setting = interpreterFactory.get(interpreterGroup.getId());
|
||||
logger.info("new setting created with " + setting.id());
|
||||
logger.info("new setting created with {}", setting.id());
|
||||
return new JsonResponse(Status.CREATED, "", setting).build();
|
||||
} catch (InterpreterException e) {
|
||||
logger.error("Exception in InterpreterRestApi while creating ", e);
|
||||
|
|
@ -195,4 +197,59 @@ public class InterpreterRestApi {
|
|||
Map<String, RegisteredInterpreter> m = Interpreter.registeredInterpreters;
|
||||
return new JsonResponse(Status.OK, "", m).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* List of dependency resolving repositories
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("repository")
|
||||
public Response listRepositories() {
|
||||
List<RemoteRepository> interpreterRepositories = null;
|
||||
interpreterRepositories = interpreterFactory.getRepositories();
|
||||
return new JsonResponse(Status.OK, "", interpreterRepositories).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new repository
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
@POST
|
||||
@Path("repository")
|
||||
public Response addRepository(String message) {
|
||||
try {
|
||||
Repository request = gson.fromJson(message, Repository.class);
|
||||
interpreterFactory.addRepository(
|
||||
request.getId(),
|
||||
request.getUrl(),
|
||||
request.isSnapshot(),
|
||||
request.getAuthentication());
|
||||
logger.info("New repository {} added", request.getId());
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception in InterpreterRestApi while adding repository ", e);
|
||||
return new JsonResponse(
|
||||
Status.INTERNAL_SERVER_ERROR, e.getMessage(), ExceptionUtils.getStackTrace(e)).build();
|
||||
}
|
||||
return new JsonResponse(Status.CREATED).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete repository
|
||||
* @param repoId
|
||||
* @return
|
||||
*/
|
||||
@DELETE
|
||||
@Path("repository/{repoId}")
|
||||
public Response removeRepository(@PathParam("repoId") String repoId) {
|
||||
logger.info("Remove repository {}", repoId);
|
||||
try {
|
||||
interpreterFactory.removeRepository(repoId);
|
||||
} catch (Exception e) {
|
||||
logger.error("Exception in InterpreterRestApi while removing repository ", e);
|
||||
return new JsonResponse(
|
||||
Status.INTERNAL_SERVER_ERROR, e.getMessage(), ExceptionUtils.getStackTrace(e)).build();
|
||||
}
|
||||
return new JsonResponse(Status.OK).build();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,8 +102,9 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
@Test
|
||||
public void testSettingsCRUD() throws IOException {
|
||||
// Call Create Setting REST API
|
||||
String jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"},\"" +
|
||||
"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]}";
|
||||
String jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"}," +
|
||||
"\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]," +
|
||||
"\"dependencies\":[]}";
|
||||
PostMethod post = httpPost("/interpreter/setting/", jsonRequest);
|
||||
LOG.info("testSettingCRUD create response\n" + post.getResponseBodyAsString());
|
||||
assertThat("test create method:", post, isCreated());
|
||||
|
|
@ -116,8 +117,9 @@ public class ZeppelinRestApiTest extends AbstractTestRestApi {
|
|||
post.releaseConnection();
|
||||
|
||||
// Call Update Setting REST API
|
||||
jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"Otherpropvalue\"},\"" +
|
||||
"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]}";
|
||||
jsonRequest = "{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"Otherpropvalue\"}," +
|
||||
"\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]," +
|
||||
"\"dependencies\":[]}";
|
||||
PutMethod put = httpPut("/interpreter/setting/" + newSettingId, jsonRequest);
|
||||
LOG.info("testSettingCRUD update response\n" + put.getResponseBodyAsString());
|
||||
assertThat("test update method:", put, isAllowed());
|
||||
|
|
|
|||
|
|
@ -13,15 +13,15 @@ limitations under the License.
|
|||
-->
|
||||
<div>
|
||||
<div class="row interpreter">
|
||||
<div class="col-md-12">
|
||||
<div class="interpreterSettingAdd" ng-show="showAddNewSetting">
|
||||
<hr />
|
||||
<div class="col-md-12" ng-show="showAddNewSetting">
|
||||
<hr />
|
||||
<div class="interpreterSettingAdd">
|
||||
<h4>Create new interpreter</h4>
|
||||
|
||||
<div class="form-group" style="width:200px">
|
||||
<b>Name</b>
|
||||
<input id="newInterpreterSettingName" input pu-elastic-input
|
||||
pu-elastic-input-minwidth="180px" ng-model="newInterpreterSetting.name" />
|
||||
pu-elastic-input-minwidth="180px" ng-model="newInterpreterSetting.name">
|
||||
</div>
|
||||
|
||||
<b>Interpreter</b>
|
||||
|
|
@ -56,7 +56,7 @@ limitations under the License.
|
|||
<tr>
|
||||
<td>
|
||||
<input pu-elastic-input pu-elastic-input-minwidth="180px"
|
||||
ng-model="newInterpreterSetting.propertyKey" />
|
||||
ng-model="newInterpreterSetting.propertyKey">
|
||||
</td>
|
||||
<td><textarea msd-elastic ng-model="newInterpreterSetting.propertyValue"></textarea></td>
|
||||
<td></td>
|
||||
|
|
@ -77,7 +77,7 @@ limitations under the License.
|
|||
|
||||
<tr ng-repeat="dep in newInterpreterSetting.dependencies">
|
||||
<td>
|
||||
<input ng-model="dep.groupArtifactVersion" style="width:100%"/>
|
||||
<input ng-model="dep.groupArtifactVersion" style="width:100%">
|
||||
</td>
|
||||
<td>
|
||||
<textarea msd-elastic ng-model="dep.exclusions"
|
||||
|
|
@ -96,7 +96,7 @@ limitations under the License.
|
|||
<td>
|
||||
<input ng-model="newInterpreterSetting.depArtifact"
|
||||
placeholder="groupId:artifactId:version or local file path"
|
||||
style="width: 100%"/>
|
||||
style="width: 100%">
|
||||
</td>
|
||||
<td>
|
||||
<textarea msd-elastic ng-model="newInterpreterSetting.depExclude"
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
|
|||
$scope.interpreterSettings = [];
|
||||
$scope.availableInterpreters = {};
|
||||
$scope.showAddNewSetting = false;
|
||||
$scope.showRepositoryInfo = false;
|
||||
$scope._ = _;
|
||||
|
||||
var getInterpreterSettings = function() {
|
||||
|
|
@ -320,10 +321,74 @@ angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
|
|||
}
|
||||
};
|
||||
|
||||
$scope.resetNewRepositorySetting = function() {
|
||||
$scope.newRepoSetting = {
|
||||
id: undefined,
|
||||
url: undefined,
|
||||
snapshot: false,
|
||||
username: undefined,
|
||||
password: undefined
|
||||
};
|
||||
};
|
||||
|
||||
var getRepositories = function() {
|
||||
$http.get(baseUrlSrv.getRestApiBase() + '/interpreter/repository').
|
||||
success(function(data, status, headers, config) {
|
||||
$scope.repositories = data.body;
|
||||
}).
|
||||
error(function(data, status, headers, config) {
|
||||
console.log('Error %o %o', status, data.message);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.addNewRepository = function() {
|
||||
var request = angular.copy($scope.newRepoSetting);
|
||||
|
||||
$http.post(baseUrlSrv.getRestApiBase() + '/interpreter/repository', request).
|
||||
success(function(data, status, headers, config) {
|
||||
getRepositories();
|
||||
$scope.resetNewRepositorySetting();
|
||||
angular.element('#repoModal').modal('hide');
|
||||
}).
|
||||
error(function(data, status, headers, config) {
|
||||
console.log('Error %o %o', headers, config);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.removeRepository = function(repoId) {
|
||||
BootstrapDialog.confirm({
|
||||
closable: true,
|
||||
title: '',
|
||||
message: 'Do you want to delete this repository?',
|
||||
callback: function(result) {
|
||||
if (result) {
|
||||
$http.delete(baseUrlSrv.getRestApiBase()+'/interpreter/repository/' + repoId).
|
||||
success(function(data, status, headers, config) {
|
||||
var index = _.findIndex($scope.repositories, { 'id': repoId });
|
||||
$scope.repositories.splice(index, 1);
|
||||
}).
|
||||
error(function(data, status, headers, config) {
|
||||
console.log('Error %o %o', status, data.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$scope.isDefaultRepository = function(repoId) {
|
||||
if (repoId === 'central' || repoId === 'local') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var init = function() {
|
||||
$scope.resetNewInterpreterSetting();
|
||||
$scope.resetNewRepositorySetting();
|
||||
getInterpreterSettings();
|
||||
getAvailableInterpreters();
|
||||
getRepositories();
|
||||
};
|
||||
|
||||
init();
|
||||
|
|
|
|||
|
|
@ -88,6 +88,11 @@
|
|||
float: left;
|
||||
}
|
||||
|
||||
.empty-properties-message {
|
||||
.gray40-message {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.blackOpc:hover {
|
||||
color: #000;
|
||||
opacity: .5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,11 +18,18 @@ limitations under the License.
|
|||
<h3 class="new_h3">
|
||||
Interpreters
|
||||
</h3>
|
||||
<span class="btn btn-default fa fa-plus"
|
||||
ng-click="showAddNewSetting = !showAddNewSetting"
|
||||
style="float:right;margin-top:10px;">
|
||||
Create
|
||||
</span>
|
||||
<div class="pull-right" style="margin-top:10px;">
|
||||
<span class="btn btn-default fa fa-plus"
|
||||
ng-click="showAddNewSetting = !showAddNewSetting"
|
||||
style="margin-right:6px;">
|
||||
Create
|
||||
</span>
|
||||
<span style="cursor:pointer;margin-right:4px;"
|
||||
ng-click="showRepositoryInfo = !showRepositoryInfo"
|
||||
tooltip-placement="bottom" tooltip="Repository information">
|
||||
<i class="fa fa-cog" ng-style="{color: showRepositoryInfo ? '#3071A9' : 'black' }"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
|
@ -31,6 +38,42 @@ limitations under the License.
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row" ng-if="showRepositoryInfo">
|
||||
<div class="col-md-12">
|
||||
<hr />
|
||||
<h4>Repositories</h4>
|
||||
<p>Available repository lists. These repositories are used to resolve external dependencies of interpreter.</p>
|
||||
<ul class="noDot">
|
||||
<li class="liVertical" ng-repeat="repo in repositories">
|
||||
<a tabindex="0" class="btn btn-info" role="button"
|
||||
popover-trigger="focus"
|
||||
popover-placement="right"
|
||||
popover-html-unsafe="
|
||||
<label>URL: </label>
|
||||
{{repo.url}}<br>
|
||||
<label>Snapshot: </label>
|
||||
{{repo.snapshotPolicy.enabled}}<br>
|
||||
<label>Username: </label>
|
||||
{{repo.authentication.username}}">
|
||||
<span class="fa fa-database"></span>
|
||||
{{repo.id}}
|
||||
<span ng-if="!isDefaultRepository(repo.id)"
|
||||
class="fa fa-close blackOpc" ng-click="removeRepository(repo.id)"></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="liVertical">
|
||||
<div ng-include src="'components/repository-create/repository-dialog.html'"></div>
|
||||
<div class="btn btn-default"
|
||||
data-toggle="modal"
|
||||
data-target="#repoModal">
|
||||
<span class="fa fa-plus"></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ng-include src="'app/interpreter/interpreter-create/interpreter-create.html'"></div>
|
||||
</div>
|
||||
|
||||
|
|
@ -66,8 +109,8 @@ limitations under the License.
|
|||
</div>
|
||||
</div>
|
||||
<div class="row interpreter">
|
||||
<div ng-show="_.isEmpty(setting.properties) || valueform.$hidden" class="col-md-12 empty-properties-message">
|
||||
<em>Currently there are no properties set for this interpreter</em>
|
||||
<div ng-show="_.isEmpty(setting.properties) && _.isEmpty(setting.dependencies) || valueform.$hidden" class="col-md-12 gray40-message">
|
||||
<em>Currently there are no properties and dependencies set for this interpreter</em>
|
||||
</div>
|
||||
<div class="col-md-12" ng-show="!_.isEmpty(setting.properties) || valueform.$visible">
|
||||
<h5>Properties</h5>
|
||||
|
|
@ -97,7 +140,6 @@ limitations under the License.
|
|||
<input ng-model="setting.propertyKey"
|
||||
pu-elastic-input
|
||||
pu-elastic-input-minwidth="180px">
|
||||
</input>
|
||||
</td>
|
||||
<td>
|
||||
<textarea msd-elastic ng-model="setting.propertyValue"></textarea>
|
||||
|
|
@ -113,6 +155,8 @@ limitations under the License.
|
|||
|
||||
<div class="col-md-12" ng-show="!_.isEmpty(setting.dependencies) || valueform.$visible">
|
||||
<h5>Dependencies</h5>
|
||||
<p class="gray40-message" style="font-size:12px" ng-show="valueform.$visible">
|
||||
These dependencies will be added to classpath when interpreter process starts.</p>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
|
|
@ -148,7 +192,6 @@ limitations under the License.
|
|||
<input ng-model="setting.depArtifact"
|
||||
placeholder="groupId:artifactId:version or local file path"
|
||||
style="width: 100%">
|
||||
</input>
|
||||
</td>
|
||||
<td>
|
||||
<textarea ng-model="setting.depExclude"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
<!--
|
||||
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 id="repoModal" class="modal fade" role="dialog"
|
||||
tabindex='-1'>
|
||||
<div class="modal-dialog">
|
||||
|
||||
<!-- Modal content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title">Add New Repository</h4>
|
||||
</div>
|
||||
|
||||
<form class="form-horizontal" ng-submit="addNewRepository()">
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="repoId">ID</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="repoId" ng-model="newRepoSetting.id"
|
||||
placeholder="Repository id" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="repoUrl">URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="url" class="form-control" id="repoUrl" ng-model="newRepoSetting.url"
|
||||
placeholder="Repository url" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="repoSnapshot">Snapshot</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" id="repoSnapshot" ng-model="newRepoSetting.snapshot">
|
||||
<option ng-selected="true">false</option>
|
||||
<option>true</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="repoUsername">Username</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="repoUsername" ng-model="newRepoSetting.username">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="repoPassword">Password</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" id="repoPassword" ng-model="newRepoSetting.password">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit"
|
||||
class="btn btn-default">Add
|
||||
</button>
|
||||
<button type="button" data-dismiss="modal"
|
||||
class="btn btn-default" ng-click="resetNewRepositorySetting()">Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -63,8 +63,8 @@ limitations under the License.
|
|||
</head>
|
||||
<body ng-class="{'bodyAsIframe': asIframe}" >
|
||||
<!--[if lt IE 7]>
|
||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
||||
<![endif]-->
|
||||
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
|
||||
<![endif]-->
|
||||
<toast></toast>
|
||||
<div ng-include src="'components/navbar/navbar.html'"></div>
|
||||
<!-- Add your site or application content here -->
|
||||
|
|
@ -81,9 +81,9 @@ limitations under the License.
|
|||
</div>
|
||||
<!-- build:js(.) scripts/oldieshim.js -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="bower_components/es5-shim/es5-shim.js"></script>
|
||||
<script src="bower_components/json3/lib/json3.min.js"></script>
|
||||
<![endif]-->
|
||||
<script src="bower_components/es5-shim/es5-shim.js"></script>
|
||||
<script src="bower_components/json3/lib/json3.min.js"></script>
|
||||
<![endif]-->
|
||||
<!-- endbuild -->
|
||||
|
||||
<!-- build:js(.) scripts/vendor.js -->
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ import org.apache.zeppelin.scheduler.Job.Status;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.sonatype.aether.RepositoryException;
|
||||
import org.sonatype.aether.repository.Authentication;
|
||||
import org.sonatype.aether.repository.RemoteRepository;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
|
@ -64,6 +66,7 @@ public class InterpreterFactory {
|
|||
new HashMap<String, InterpreterSetting>();
|
||||
|
||||
private Map<String, List<String>> interpreterBindings = new HashMap<String, List<String>>();
|
||||
private List<RemoteRepository> interpreterRepositories;
|
||||
|
||||
private Gson gson;
|
||||
|
||||
|
|
@ -93,6 +96,7 @@ public class InterpreterFactory {
|
|||
this.defaultOption = defaultOption;
|
||||
this.angularObjectRegistryListener = angularObjectRegistryListener;
|
||||
this.depResolver = depResolver;
|
||||
this.interpreterRepositories = depResolver.getRepos();
|
||||
this.remoteInterpreterProcessListener = remoteInterpreterProcessListener;
|
||||
String replsConf = conf.getString(ConfVars.ZEPPELIN_INTERPRETERS);
|
||||
interpreterClassList = replsConf.split(",");
|
||||
|
|
@ -194,7 +198,7 @@ public class InterpreterFactory {
|
|||
logger.info("Interpreter setting group {} : id={}, name={}",
|
||||
setting.getGroup(), settingId, setting.getName());
|
||||
for (Interpreter interpreter : setting.getInterpreterGroup()) {
|
||||
logger.info(" className = {}", interpreter.getClassName());
|
||||
logger.info(" className = {}", interpreter.getClassName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -251,6 +255,14 @@ public class InterpreterFactory {
|
|||
}
|
||||
|
||||
this.interpreterBindings = info.interpreterBindings;
|
||||
|
||||
if (info.interpreterRepositories != null) {
|
||||
for (RemoteRepository repo : info.interpreterRepositories) {
|
||||
if (!depResolver.getRepos().contains(repo)) {
|
||||
this.interpreterRepositories.add(repo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadInterpreterDependencies(InterpreterSetting intSetting)
|
||||
|
|
@ -286,6 +298,7 @@ public class InterpreterFactory {
|
|||
InterpreterInfoSaving info = new InterpreterInfoSaving();
|
||||
info.interpreterBindings = interpreterBindings;
|
||||
info.interpreterSettings = interpreterSettings;
|
||||
info.interpreterRepositories = interpreterRepositories;
|
||||
|
||||
jsonString = gson.toJson(info);
|
||||
}
|
||||
|
|
@ -736,4 +749,19 @@ public class InterpreterFactory {
|
|||
return new URL[] {path.toURI().toURL()};
|
||||
}
|
||||
}
|
||||
|
||||
public List<RemoteRepository> getRepositories() {
|
||||
return this.interpreterRepositories;
|
||||
}
|
||||
|
||||
public void addRepository(String id, String url, boolean snapshot, Authentication auth)
|
||||
throws IOException {
|
||||
depResolver.addRepo(id, url, snapshot, auth);
|
||||
saveToFile();
|
||||
}
|
||||
|
||||
public void removeRepository(String id) throws IOException {
|
||||
depResolver.delRepo(id);
|
||||
saveToFile();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package org.apache.zeppelin.interpreter;
|
||||
|
||||
import org.sonatype.aether.repository.RemoteRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
|
@ -26,4 +28,5 @@ import java.util.Map;
|
|||
public class InterpreterInfoSaving {
|
||||
public Map<String, InterpreterSetting> interpreterSettings;
|
||||
public Map<String, List<String>> interpreterBindings;
|
||||
public List<RemoteRepository> interpreterRepositories;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import org.apache.commons.lang.NullArgumentException;
|
|||
import org.apache.zeppelin.conf.ZeppelinConfiguration;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
|
||||
import org.apache.zeppelin.dep.Dependency;
|
||||
import org.apache.zeppelin.dep.DependencyResolver;
|
||||
import org.apache.zeppelin.interpreter.mock.MockInterpreter1;
|
||||
import org.apache.zeppelin.interpreter.mock.MockInterpreter2;
|
||||
import org.junit.After;
|
||||
|
|
@ -45,6 +46,7 @@ public class InterpreterFactoryTest {
|
|||
private File tmpDir;
|
||||
private ZeppelinConfiguration conf;
|
||||
private InterpreterContext context;
|
||||
private DependencyResolver depResolver;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
|
@ -58,7 +60,8 @@ public class InterpreterFactoryTest {
|
|||
System.setProperty(ConfVars.ZEPPELIN_HOME.getVarName(), tmpDir.getAbsolutePath());
|
||||
System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), "org.apache.zeppelin.interpreter.mock.MockInterpreter1,org.apache.zeppelin.interpreter.mock.MockInterpreter2");
|
||||
conf = new ZeppelinConfiguration();
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null);
|
||||
depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo");
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, depResolver);
|
||||
context = new InterpreterContext("note", "id", "title", "text", null, null, null, null, null);
|
||||
|
||||
}
|
||||
|
|
@ -143,7 +146,7 @@ public class InterpreterFactoryTest {
|
|||
factory.add("newsetting", "mock1", new LinkedList<Dependency>(), new InterpreterOption(false), new Properties());
|
||||
assertEquals(3, factory.get().size());
|
||||
|
||||
InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, null);
|
||||
InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, null, depResolver);
|
||||
assertEquals(3, factory2.get().size());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.HashMap;
|
|||
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
|
||||
import org.apache.zeppelin.dep.DependencyResolver;
|
||||
import org.apache.zeppelin.interpreter.Interpreter;
|
||||
import org.apache.zeppelin.interpreter.InterpreterFactory;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOption;
|
||||
|
|
@ -40,6 +41,7 @@ public class NoteInterpreterLoaderTest {
|
|||
private File tmpDir;
|
||||
private ZeppelinConfiguration conf;
|
||||
private InterpreterFactory factory;
|
||||
private DependencyResolver depResolver;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
|
@ -58,7 +60,8 @@ public class NoteInterpreterLoaderTest {
|
|||
MockInterpreter11.register("mock11", "group1", "org.apache.zeppelin.interpreter.mock.MockInterpreter11");
|
||||
MockInterpreter2.register("mock2", "group2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2");
|
||||
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null);
|
||||
depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo");
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, depResolver);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import java.util.Map;
|
|||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
|
||||
import org.apache.zeppelin.dep.DependencyResolver;
|
||||
import org.apache.zeppelin.display.AngularObjectRegistry;
|
||||
import org.apache.zeppelin.interpreter.InterpreterFactory;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOption;
|
||||
|
|
@ -67,6 +68,7 @@ public class NotebookTest implements JobListenerFactory{
|
|||
private Notebook notebook;
|
||||
private NotebookRepo notebookRepo;
|
||||
private InterpreterFactory factory;
|
||||
private DependencyResolver depResolver;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
|
|
@ -87,7 +89,8 @@ public class NotebookTest implements JobListenerFactory{
|
|||
MockInterpreter1.register("mock1", "org.apache.zeppelin.interpreter.mock.MockInterpreter1");
|
||||
MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2");
|
||||
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null);
|
||||
depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo");
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, depResolver);
|
||||
|
||||
SearchService search = mock(SearchService.class);
|
||||
notebookRepo = new VFSNotebookRepo(conf);
|
||||
|
|
@ -174,8 +177,8 @@ public class NotebookTest implements JobListenerFactory{
|
|||
note.persist();
|
||||
|
||||
Notebook notebook2 = new Notebook(
|
||||
conf, notebookRepo, schedulerFactory, new InterpreterFactory(conf, null, null, null), this,
|
||||
null);
|
||||
conf, notebookRepo, schedulerFactory,
|
||||
new InterpreterFactory(conf, null, null, null, depResolver), this, null);
|
||||
assertEquals(1, notebook2.getAllNotes().size());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import java.util.Map;
|
|||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
|
||||
import org.apache.zeppelin.dep.DependencyResolver;
|
||||
import org.apache.zeppelin.interpreter.InterpreterFactory;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOption;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOutput;
|
||||
|
|
@ -57,6 +58,7 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
private Notebook notebookSync;
|
||||
private NotebookRepoSync notebookRepoSync;
|
||||
private InterpreterFactory factory;
|
||||
private DependencyResolver depResolver;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(NotebookRepoSyncTest.class);
|
||||
|
||||
@Before
|
||||
|
|
@ -85,7 +87,8 @@ public class NotebookRepoSyncTest implements JobListenerFactory {
|
|||
MockInterpreter1.register("mock1", "org.apache.zeppelin.interpreter.mock.MockInterpreter1");
|
||||
MockInterpreter2.register("mock2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2");
|
||||
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null);
|
||||
depResolver = new DependencyResolver(mainZepDir.getAbsolutePath() + "/local-repo");
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, depResolver);
|
||||
|
||||
SearchService search = mock(SearchService.class);
|
||||
notebookRepoSync = new NotebookRepoSync(conf);
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import java.util.Map;
|
|||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration;
|
||||
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
|
||||
import org.apache.zeppelin.dep.DependencyResolver;
|
||||
import org.apache.zeppelin.interpreter.InterpreterFactory;
|
||||
import org.apache.zeppelin.interpreter.InterpreterOption;
|
||||
import org.apache.zeppelin.interpreter.mock.MockInterpreter1;
|
||||
|
|
@ -48,6 +49,7 @@ public class VFSNotebookRepoTest implements JobListenerFactory {
|
|||
private Notebook notebook;
|
||||
private NotebookRepo notebookRepo;
|
||||
private InterpreterFactory factory;
|
||||
private DependencyResolver depResolver;
|
||||
|
||||
private File mainZepDir;
|
||||
private File mainNotebookDir;
|
||||
|
|
@ -73,7 +75,8 @@ public class VFSNotebookRepoTest implements JobListenerFactory {
|
|||
MockInterpreter1.register("mock1", "org.apache.zeppelin.interpreter.mock.MockInterpreter1");
|
||||
|
||||
this.schedulerFactory = new SchedulerFactory();
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null);
|
||||
depResolver = new DependencyResolver(mainZepDir.getAbsolutePath() + "/local-repo");
|
||||
factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, depResolver);
|
||||
|
||||
SearchService search = mock(SearchService.class);
|
||||
notebookRepo = new VFSNotebookRepo(conf);
|
||||
|
|
|
|||
Loading…
Reference in a new issue