1
0
Fork 0

Merge branch 'devel' of github.com:arangodb/arangodb into devel

This commit is contained in:
jsteemann 2019-10-10 15:04:39 +02:00
commit b35674dffa
14 changed files with 190 additions and 574 deletions

View File

@ -1,10 +1,9 @@
devel devel
----- -----
* Bugfix: In an AQL cluster query, when gathering unsorted data in combination * Made the mechanism in the Web UI of replacing and upgrading a foxx app more clear.
with a LIMIT with non-zero offset, if this offset exactly matches the number
of documents in the first shards consumed, the rest of the documents was not * Fixed search not working in document view while in code mode
returned.
* Show shards of all collections (including system collections) in the web UI's shard * Show shards of all collections (including system collections) in the web UI's shard
distribution view. distribution view.

View File

@ -68,11 +68,15 @@ foxxRouter.use(installer)
`) `)
.queryParam('upgrade', joi.boolean().default(false), dd` .queryParam('upgrade', joi.boolean().default(false), dd`
Flag to upgrade the service installed at the mount point. Flag to upgrade the service installed at the mount point.
Triggers setup.
`) `)
.queryParam('replace', joi.boolean().default(false), dd` .queryParam('replace', joi.boolean().default(false), dd`
Flag to replace the service installed at the mount point. Flag to replace the service installed at the mount point.
Triggers teardown and setup. `)
.queryParam('setup', joi.boolean().default(true), dd`
Flag to run setup after install.
`)
.queryParam('teardown', joi.boolean().default(false), dd`
Flag to run teardown before replace/upgrade.
`); `);
installer.use(function (req, res, next) { installer.use(function (req, res, next) {
@ -83,6 +87,8 @@ installer.use(function (req, res, next) {
const options = {}; const options = {};
const appInfo = req.body; const appInfo = req.body;
options.legacy = req.queryParams.legacy; options.legacy = req.queryParams.legacy;
options.setup = req.queryParams.setup;
options.teardown = req.queryParams.teardown;
let service; let service;
try { try {
if (upgrade) { if (upgrade) {

View File

@ -1159,18 +1159,25 @@
}); });
}, },
getFoxxFlag: function () { getFoxxFlags: function () {
var flag; var flags = {};
if ($('#new-app-replace').prop('checked')) { var $replace = $('#new-app-flag-replace')[0];
flag = true; if ($replace) {
} else { flags.replace = Boolean($replace.checked);
if ($('#new-app-teardown').prop('checked')) {
flag = false;
}
} }
return flag; var $teardown = $('#new-app-flag-teardown')[0];
if ($teardown) {
flags.teardown = Boolean($teardown.checked);
}
var $setup = $('#new-app-flag-setup')[0];
if ($setup) {
flags.setup = Boolean($setup.checked);
}
return flags;
}, },
createMountPointModal: function (callback, mode, mountpoint) { createMountPointModal: function (callback, mode, mountpoint) {
@ -1200,12 +1207,24 @@
) )
); );
if (window.App.replaceApp) {
tableContent.push(
window.modalView.createCheckboxEntry(
'new-app-flag-teardown',
'Run teardown?',
false,
"Should the existing service's teardown script be executed before replacing the service?",
false
)
);
}
tableContent.push( tableContent.push(
window.modalView.createCheckboxEntry( window.modalView.createCheckboxEntry(
'new-app-teardown', 'new-app-flag-setup',
'Run setup?', 'Run setup?',
true, true,
"Should this app's setup script be executed after installing the app?", "Should this service's setup script be executed after installing the service?",
true true
) )
); );
@ -1213,9 +1232,9 @@
if (window.App.replaceApp) { if (window.App.replaceApp) {
tableContent.push( tableContent.push(
window.modalView.createCheckboxEntry( window.modalView.createCheckboxEntry(
'new-app-replace', 'new-app-flag-replace',
'Discard configuration and dependency files?', 'Discard configuration and dependency files?',
true, false,
"Should this service's existing configuration and settings be removed completely before replacing the service?", "Should this service's existing configuration and settings be removed completely before replacing the service?",
false false
) )

View File

@ -28,19 +28,25 @@
this.sortOptions.desc = val; this.sortOptions.desc = val;
}, },
// Install Foxx from github repo install: function (mode, info, mount, options, callback) {
// info is expected to contain: "url" and "version" var url = arangoHelper.databaseUrl('/_admin/aardvark/foxxes/' + mode + '?mount=' + encodeURIComponent(mount));
installFromGithub: function (info, mount, callback, isLegacy, flag) { if (options.legacy) {
var url = arangoHelper.databaseUrl('/_admin/aardvark/foxxes/git?mount=' + encodeURIComponent(mount));
if (isLegacy) {
url += '&legacy=true'; url += '&legacy=true';
} }
if (flag !== undefined) { if (options.setup === true) {
if (flag) { url += '&setup=true';
url += '&replace=true'; } else if (options.setup === false) {
} else { url += '&setup=false';
url += '&upgrade=true'; }
} if (options.teardown === true) {
url += '&teardown=true';
} else if (options.teardown === false) {
url += '&teardown=false';
}
if (options.replace === true) {
url += '&replace=true';
} else if (options.replace === false) {
url += '&upgrade=true';
} }
$.ajax({ $.ajax({
cache: false, cache: false,
@ -58,115 +64,5 @@
}); });
}, },
// Install Foxx from public url
// info is expected to contain: "url" and "version"
installFromUrl: function (info, mount, callback, isLegacy, flag) {
var url = arangoHelper.databaseUrl('/_admin/aardvark/foxxes/url?mount=' + encodeURIComponent(mount));
if (isLegacy) {
url += '&legacy=true';
}
if (flag !== undefined) {
if (flag) {
url += '&replace=true';
} else {
url += '&upgrade=true';
}
}
$.ajax({
cache: false,
type: 'PUT',
url: url,
data: JSON.stringify(info),
contentType: 'application/json',
processData: false,
success: function (data) {
callback(data);
},
error: function (err) {
callback(err);
}
});
},
// Install Foxx from arango store
// info is expected to contain: "name" and "version"
installFromStore: function (info, mount, callback, flag) {
var url = arangoHelper.databaseUrl('/_admin/aardvark/foxxes/store?mount=' + encodeURIComponent(mount));
if (flag !== undefined) {
if (flag) {
url += '&replace=true';
} else {
url += '&upgrade=true';
}
}
$.ajax({
cache: false,
type: 'PUT',
url: url,
data: JSON.stringify(info),
contentType: 'application/json',
processData: false,
success: function (data) {
callback(data);
},
error: function (err) {
callback(err);
}
});
},
installFromZip: function (fileName, mount, callback, isLegacy, flag) {
var url = arangoHelper.databaseUrl('/_admin/aardvark/foxxes/zip?mount=' + encodeURIComponent(mount));
if (isLegacy) {
url += '&legacy=true';
}
if (flag !== undefined) {
if (flag) {
url += '&replace=true';
} else {
url += '&upgrade=true';
}
}
$.ajax({
cache: false,
type: 'PUT',
url: url,
data: JSON.stringify({zipFile: fileName}),
contentType: 'application/json',
processData: false,
success: function (data) {
callback(data);
},
error: function (err) {
callback(err);
}
});
},
generate: function (info, mount, callback, flag) {
var url = arangoHelper.databaseUrl('/_admin/aardvark/foxxes/generate?mount=' + encodeURIComponent(mount));
if (flag !== undefined) {
if (flag) {
url += '&replace=true';
} else {
url += '&upgrade=true';
}
}
$.ajax({
cache: false,
type: 'PUT',
url: url,
data: JSON.stringify(info),
contentType: 'application/json',
processData: false,
success: function (data) {
callback(data);
},
error: function (err) {
callback(err);
}
});
}
}); });
}()); }());

View File

@ -225,9 +225,6 @@
// foxxes // foxxes
this.foxxList = new window.FoxxCollection(); this.foxxList = new window.FoxxCollection();
window.foxxInstallView = new window.FoxxInstallView({
collection: this.foxxList
});
// foxx repository // foxx repository
this.foxxRepo = new window.FoxxRepository(); this.foxxRepo = new window.FoxxRepository();

View File

@ -1,392 +0,0 @@
/* jshint browser: true */
/* global $, Joi, _, arangoHelper, templateEngine, window */
(function () {
'use strict';
// mop: copy paste from common/bootstrap/errors.js
var errors = {
'ERROR_SERVICE_DOWNLOAD_FAILED': { 'code': 1752, 'message': 'service download failed' }
};
var appStoreTemplate = templateEngine.createTemplate('applicationListView.ejs');
var FoxxInstallView = function (opts) {
this.collection = opts.collection;
};
var installCallback = function (result) {
var self = this;
if (result.error === false) {
this.collection.fetch({
success: function () {
window.modalView.hide();
self.reload();
arangoHelper.arangoNotification('Services', 'Service ' + result.name + ' installed.');
}
});
} else {
var res = result;
if (result.hasOwnProperty('responseJSON')) {
res = result.responseJSON;
}
switch (res.errorNum) {
case errors.ERROR_SERVICE_DOWNLOAD_FAILED.code:
arangoHelper.arangoError('Services', 'Unable to download application from the given repository.');
break;
default:
arangoHelper.arangoError('Services', res.errorNum + '. ' + res.errorMessage);
}
}
};
var setMountpointValidators = function () {
window.modalView.modalBindValidation({
id: 'new-app-mount',
validateInput: function () {
return [
{
rule: Joi.string().regex(/(\/|^)APP(\/|$)/i, {invert: true}),
msg: 'May not contain /APP'
},
{
rule: Joi.string().regex(/^(\/[a-zA-Z0-9_\-%]+)+$/),
msg: 'Can only contain [a-zA-Z0-9_-%]'
},
{
rule: Joi.string().regex(/^\/([^_]|_open\/)/),
msg: 'Mountpoints with _ are reserved for internal use'
},
{
rule: Joi.string().regex(/[^/]$/),
msg: 'May not end with /'
},
{
rule: Joi.string().regex(/^\//),
msg: 'Has to start with /'
},
{
rule: Joi.string().required().min(2),
msg: 'Has to be non-empty'
}
];
}
});
};
var setGithubValidators = function () {
window.modalView.modalBindValidation({
id: 'repository',
validateInput: function () {
return [
{
rule: Joi.string().required().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+$/),
msg: 'No valid Github account and repository.'
}
];
}
});
};
var setNewAppValidators = function () {
window.modalView.modalBindValidation({
id: 'new-app-author',
validateInput: function () {
return [
{
rule: Joi.string().required().min(1),
msg: 'Has to be non empty.'
}
];
}
});
window.modalView.modalBindValidation({
id: 'new-app-name',
validateInput: function () {
return [
{
rule: Joi.string().required().regex(/^[a-zA-Z\-_][a-zA-Z0-9\-_]*$/),
msg: "Can only contain a to z, A to Z, 0-9, '-' and '_'. Cannot start with a number."
}
];
}
});
window.modalView.modalBindValidation({
id: 'new-app-description',
validateInput: function () {
return [
{
rule: Joi.string().required().min(1),
msg: 'Has to be non empty.'
}
];
}
});
window.modalView.modalBindValidation({
id: 'new-app-license',
validateInput: function () {
return [
{
rule: Joi.string().required().regex(/^[a-zA-Z0-9 .,;-]+$/),
msg: "Can only contain a to z, A to Z, 0-9, '-', '.', ',' and ';'."
}
];
}
});
window.modalView.modalTestAll();
};
var switchTab = function (openTab) {
window.modalView.clearValidators();
var button = $('#modalButton1');
if (!this._upgrade) {
setMountpointValidators();
}
switch (openTab) {
case 'newApp':
button.html('Generate');
button.prop('disabled', false);
setNewAppValidators();
break;
case 'appstore':
button.html('Install');
button.prop('disabled', true);
break;
case 'github':
setGithubValidators();
button.html('Install');
button.prop('disabled', false);
break;
case 'zip':
button.html('Install');
button.prop('disabled', false);
break;
default:
}
if (!button.prop('disabled') && !window.modalView.modalTestAll()) {
// trigger the validation so the "ok" button has the correct state
button.prop('disabled', true);
}
};
var switchModalButton = function (event) {
var openTab = $(event.currentTarget).attr('href').substr(1);
switchTab.call(this, openTab);
};
var installFoxxFromStore = function (e) {
switchTab.call(this, 'appstore');
if (window.modalView.modalTestAll()) {
var mount, flag;
if (this._upgrade) {
mount = this.mount;
flag = $('#new-app-teardown').prop('checked');
} else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
}
var toInstall = $(e.currentTarget).attr('appId');
var version = $(e.currentTarget).attr('appVersion');
if (flag !== undefined) {
this.collection.installFromStore({name: toInstall, version: version}, mount, installCallback.bind(this), flag);
} else {
this.collection.installFromStore({name: toInstall, version: version}, mount, installCallback.bind(this));
}
window.modalView.hide();
arangoHelper.arangoNotification('Services', 'Installing ' + toInstall + '.');
}
};
var installFoxxFromZip = function (files, data) {
if (data === undefined) {
data = this._uploadData;
} else {
this._uploadData = data;
}
if (data && window.modalView.modalTestAll()) {
var mount, flag, isLegacy;
if (this._upgrade) {
mount = this.mount;
flag = Boolean($('#new-app-teardown').prop('checked'));
} else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
}
isLegacy = Boolean($('#zip-app-islegacy').prop('checked'));
this.collection.installFromZip(data.filename, mount, installCallback.bind(this), isLegacy, flag);
}
};
var installFoxxFromGithub = function () {
if (window.modalView.modalTestAll()) {
var url, version, mount, flag, isLegacy;
if (this._upgrade) {
mount = this.mount;
flag = $('#new-app-teardown').prop('checked');
} else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
}
url = window.arangoHelper.escapeHtml($('#repository').val());
version = window.arangoHelper.escapeHtml($('#tag').val());
if (version === '') {
version = 'master';
}
var info = {
url: window.arangoHelper.escapeHtml($('#repository').val()),
version: window.arangoHelper.escapeHtml($('#tag').val())
};
try {
Joi.assert(url, Joi.string().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+$/));
} catch (e) {
return;
}
// send server req through collection
isLegacy = Boolean($('#github-app-islegacy').prop('checked'));
this.collection.installFromGithub(info, mount, installCallback.bind(this), isLegacy, flag);
}
};
var generateNewFoxxApp = function () {
if (window.modalView.modalTestAll()) {
var mount, flag;
if (this._upgrade) {
mount = this.mount;
flag = $('#new-app-teardown').prop('checked');
} else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
}
var info = {
name: window.arangoHelper.escapeHtml($('#new-app-name').val()),
documentCollections: _.map($('#new-app-document-collections').select2('data'), function (d) {
return window.arangoHelper.escapeHtml(d.text);
}),
edgeCollections: _.map($('#new-app-edge-collections').select2('data'), function (d) {
return window.arangoHelper.escapeHtml(d.text);
}),
// authenticated: window.arangoHelper.escapeHtml($("#new-app-name").val()),
author: window.arangoHelper.escapeHtml($('#new-app-author').val()),
license: window.arangoHelper.escapeHtml($('#new-app-license').val()),
description: window.arangoHelper.escapeHtml($('#new-app-description').val())
};
this.collection.generate(info, mount, installCallback.bind(this), flag);
}
};
var addAppAction = function () {
var openTab = $('.modal-body .tab-pane.active').attr('id');
switch (openTab) {
case 'newApp':
generateNewFoxxApp.apply(this);
break;
case 'github':
installFoxxFromGithub.apply(this);
break;
case 'zip':
installFoxxFromZip.apply(this);
break;
default:
}
};
var render = function (scope, upgrade) {
var buttons = [];
var modalEvents = {
'click #infoTab a': switchModalButton.bind(scope),
'click .install-app': installFoxxFromStore.bind(scope)
};
buttons.push(
window.modalView.createSuccessButton('Generate', addAppAction.bind(scope))
);
window.modalView.show(
'modalApplicationMount.ejs',
'Install Service',
buttons,
upgrade,
undefined,
undefined,
modalEvents
);
$('#new-app-document-collections').select2({
tags: [],
showSearchBox: false,
minimumResultsForSearch: -1,
width: '336px'
});
$('#new-app-edge-collections').select2({
tags: [],
showSearchBox: false,
minimumResultsForSearch: -1,
width: '336px'
});
var checkButton = function () {
var button = $('#modalButton1');
if (!button.prop('disabled') && !window.modalView.modalTestAll()) {
button.prop('disabled', true);
} else {
button.prop('disabled', false);
}
};
$('.select2-search-field input').focusout(function () {
checkButton();
window.setTimeout(function () {
if ($('.select2-drop').is(':visible')) {
if (!$('#select2-search-field input').is(':focus')) {
$('#s2id_new-app-document-collections').select2('close');
$('#s2id_new-app-edge-collections').select2('close');
checkButton();
}
}
}, 200);
});
$('.select2-search-field input').focusin(function () {
if ($('.select2-drop').is(':visible')) {
var button = $('#modalButton1');
button.prop('disabled', true);
}
});
$('#upload-foxx-zip').uploadFile({
url: arangoHelper.databaseUrl('/_api/upload?multipart=true'),
allowedTypes: 'zip,js',
multiple: false,
onSuccess: installFoxxFromZip.bind(scope)
});
$.get('foxxes/fishbowl', function (list) {
var table = $('#appstore-content');
table.html('');
_.each(_.sortBy(list, 'name'), function (app) {
table.append(appStoreTemplate.render(app));
});
}).fail(function () {
var table = $('#appstore-content');
table.append('<tr><td>Store is not available. ArangoDB is not able to connect to github.com</td></tr>');
});
};
FoxxInstallView.prototype.install = function (callback) {
this.reload = callback;
this._upgrade = false;
this._uploadData = undefined;
delete this.mount;
render(this, false);
window.modalView.clearValidators();
setMountpointValidators();
setNewAppValidators();
};
FoxxInstallView.prototype.upgrade = function (mount, callback) {
this.reload = callback;
this._upgrade = true;
this._uploadData = undefined;
this.mount = mount;
render(this, true);
window.modalView.clearValidators();
setNewAppValidators();
};
window.FoxxInstallView = FoxxInstallView;
}());

View File

@ -201,21 +201,23 @@
installFoxxFromStore: function (e) { installFoxxFromStore: function (e) {
if (window.modalView.modalTestAll()) { if (window.modalView.modalTestAll()) {
var mount, flag; var mount, info, options;
if (this._upgrade) { if (this._upgrade) {
mount = window.App.replaceAppData.mount; mount = window.App.replaceAppData.mount;
flag = arangoHelper.getFoxxFlag();
} else { } else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val()); mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
if (mount.charAt(0) !== '/') { if (mount.charAt(0) !== '/') {
mount = '/' + mount; mount = '/' + mount;
} }
} }
if (flag !== undefined) {
this.collection.installFromStore({name: this.toInstall, version: this.version}, mount, this.installCallback.bind(this), flag); info = {
} else { name: this.toInstall,
this.collection.installFromStore({name: this.toInstall, version: this.version}, mount, this.installCallback.bind(this)); version: this.version
} };
options = arangoHelper.getFoxxFlags();
this.collection.install('store', info, mount, options, this.installCallback.bind(this));
window.modalView.hide(); window.modalView.hide();
if (this._upgrade) { if (this._upgrade) {

View File

@ -73,35 +73,36 @@
installFoxxFromGithub: function () { installFoxxFromGithub: function () {
if (window.modalView.modalTestAll()) { if (window.modalView.modalTestAll()) {
var url, version, mount, flag, isLegacy; var mount, info, options, url, version;
if (this._upgrade) { if (this._upgrade) {
mount = window.App.replaceAppData.mount; mount = window.App.replaceAppData.mount;
flag = arangoHelper.getFoxxFlag();
} else { } else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val()); mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
if (mount.charAt(0) !== '/') { if (mount.charAt(0) !== '/') {
mount = '/' + mount; mount = '/' + mount;
} }
} }
url = window.arangoHelper.escapeHtml($('#repository').val()); url = window.arangoHelper.escapeHtml($('#repository').val());
version = window.arangoHelper.escapeHtml($('#tag').val()); version = window.arangoHelper.escapeHtml($('#tag').val());
if (version === '') { if (version === '') {
version = 'master'; version = 'master';
} }
var info = {
url: window.arangoHelper.escapeHtml($('#repository').val()),
version: window.arangoHelper.escapeHtml($('#tag').val())
};
try { try {
Joi.assert(url, Joi.string().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+$/)); Joi.assert(url, Joi.string().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+$/));
} catch (e) { } catch (e) {
return; return;
} }
// send server req through collection // send server req through collection
isLegacy = Boolean($('#github-app-islegacy').prop('checked'));
this.collection.installFromGithub(info, mount, this.installCallback.bind(this), isLegacy, flag); info = {
url: url,
version: version
};
options = arangoHelper.getFoxxFlags();
options.legacy = Boolean($('#github-app-islegacy')[0].checked);
this.collection.install('git', info, mount, options, this.installCallback.bind(this));
} }
}, },

View File

@ -56,17 +56,17 @@
generateNewFoxxApp: function () { generateNewFoxxApp: function () {
if (window.modalView.modalTestAll()) { if (window.modalView.modalTestAll()) {
var mount, flag; var mount, info, options;
if (this._upgrade) { if (this._upgrade) {
mount = window.App.replaceAppData.mount; mount = window.App.replaceAppData.mount;
flag = arangoHelper.getFoxxFlag();
} else { } else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val()); mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
if (mount.charAt(0) !== '/') { if (mount.charAt(0) !== '/') {
mount = '/' + mount; mount = '/' + mount;
} }
} }
var info = {
info = {
name: window.arangoHelper.escapeHtml($('#new-app-name').val()), name: window.arangoHelper.escapeHtml($('#new-app-name').val()),
documentCollections: _.map($('#new-app-document-collections').select2('data'), function (d) { documentCollections: _.map($('#new-app-document-collections').select2('data'), function (d) {
return window.arangoHelper.escapeHtml(d.text); return window.arangoHelper.escapeHtml(d.text);
@ -79,7 +79,9 @@
license: window.arangoHelper.escapeHtml($('#new-app-license').val()), license: window.arangoHelper.escapeHtml($('#new-app-license').val()),
description: window.arangoHelper.escapeHtml($('#new-app-description').val()) description: window.arangoHelper.escapeHtml($('#new-app-description').val())
}; };
this.collection.generate(info, mount, this.installCallback.bind(this), flag);
options = arangoHelper.getFoxxFlags();
this.collection.install('generate', info, mount, options, this.installCallback.bind(this));
} }
window.modalView.hide(); window.modalView.hide();
}, },

View File

@ -71,18 +71,23 @@
this._uploadData = window.foxxData.data; this._uploadData = window.foxxData.data;
} }
if (window.foxxData.data && window.modalView.modalTestAll()) { if (window.foxxData.data && window.modalView.modalTestAll()) {
var mount, flag, isLegacy; var mount, info, options;
if (this._upgrade) { if (this._upgrade) {
mount = window.App.replaceAppData.mount; mount = window.App.replaceAppData.mount;
flag = arangoHelper.getFoxxFlag();
} else { } else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val()); mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
if (mount.charAt(0) !== '/') { if (mount.charAt(0) !== '/') {
mount = '/' + mount; mount = '/' + mount;
} }
} }
isLegacy = Boolean($('#zip-app-islegacy').prop('checked'));
this.collection.installFromZip(window.foxxData.data.filename, mount, this.installCallback.bind(this), isLegacy, flag); info = {
zipFile: window.foxxData.data.filename
};
options = arangoHelper.getFoxxFlags();
options.legacy = Boolean($('#zip-app-islegacy')[0].checked);
this.collection.install('zip', info, mount, options, this.installCallback.bind(this));
} }
window.modalView.hide(); window.modalView.hide();
}, },

View File

@ -65,11 +65,9 @@
installFoxxFromUrl: function () { installFoxxFromUrl: function () {
if (window.modalView.modalTestAll()) { if (window.modalView.modalTestAll()) {
var url, mount, flag; var mount, info, options, url;
if (this._upgrade) { if (this._upgrade) {
mount = window.App.replaceAppData.mount; mount = window.App.replaceAppData.mount;
flag = arangoHelper.getFoxxFlag();
} else { } else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val()); mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
if (mount.charAt(0) !== '/') { if (mount.charAt(0) !== '/') {
@ -77,13 +75,14 @@
} }
} }
url = window.arangoHelper.escapeHtml($('#repository').val()); url = window.arangoHelper.escapeHtml($('#repository').val());
var info = {
url: url, info = {
version: 'master' url: url
}; };
// send server req through collection // send server req through collection
this.collection.installFromUrl(info, mount, this.installCallback.bind(this), null, flag); options = arangoHelper.getFoxxFlags();
this.collection.install('url', info, mount, options, this.installCallback.bind(this));
} }
}, },

View File

@ -34,21 +34,24 @@
installFoxxFromStore: function (e) { installFoxxFromStore: function (e) {
if (window.modalView.modalTestAll()) { if (window.modalView.modalTestAll()) {
var mount, flag; var mount, info, options;
if (this._upgrade) { if (this._upgrade) {
mount = this.mount; mount = this.mount;
flag = $('#new-app-teardown').prop('checked');
} else { } else {
mount = window.arangoHelper.escapeHtml($('#new-app-mount').val()); mount = window.arangoHelper.escapeHtml($('#new-app-mount').val());
if (mount.charAt(0) !== '/') { if (mount.charAt(0) !== '/') {
mount = '/' + mount; mount = '/' + mount;
} }
} }
if (flag !== undefined) {
this.collection.installFromStore({name: this.model.get('name'), version: this.model.get('latestVersion')}, mount, this.installCallback.bind(this), flag); info = {
} else { name: this.model.get('name'),
this.collection.installFromStore({name: this.model.get('name'), version: this.model.get('latestVersion')}, mount, this.installCallback.bind(this)); version: this.model.get('latestVersion')
} };
options = arangoHelper.getFoxxFlags();
this.collection.install('store', info, mount, options, this.installCallback.bind(this));
window.modalView.hide(); window.modalView.hide();
arangoHelper.arangoNotification('Services', 'Installing ' + this.model.get('name') + '.'); arangoHelper.arangoNotification('Services', 'Installing ' + this.model.get('name') + '.');
} }

View File

@ -68,6 +68,7 @@
"/img": "frontend/compressed-img", "/img": "frontend/compressed-img",
"/data": "frontend/data", "/data": "frontend/data",
"/js/arango/aqltemplates.json": "frontend/aqltemplates.json", "/js/arango/aqltemplates.json": "frontend/aqltemplates.json",
"/ext-searchbox.js": "frontend/src/ext-searchbox.js",
"/worker-json.js": { "/worker-json.js": {
"path": "frontend/src/worker-json.js", "path": "frontend/src/worker-json.js",
"gzip": true "gzip": true

View File

@ -0,0 +1,78 @@
/*jshint globalstrict:true, strict:true, esnext: true */
'use strict';
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2019 ArangoDB GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Tobias Gödderz
////////////////////////////////////////////////////////////////////////////////
const _ = require('lodash');
const internal = require("internal");
const jsunity = require("jsunity");
const {assertEqual} = jsunity.jsUnity.assertions;
const db = internal.db;
function aqlSkippingClusterTestsuite () {
const colName = 'UnitTestsAhuacatlSkipCluster';
const numberOfShards = 16;
let col;
return {
setUpAll: function () {
col = db._create(colName, {numberOfShards});
},
tearDownAll: function () {
col.drop();
},
/**
* Regression test for PR https://github.com/arangodb/arangodb/pull/10190.
* This bug was never in a released version.
* In an AQL cluster query, when gathering unsorted data in combination with a LIMIT with non-zero offset,
* if this offset exactly matches the number of documents in the first shards consumed, the rest of the documents
* was not returned.
* The test is undeterministic, but has a high chance to detect this problem.
* This can only trigger when we skip a shard with the exact number of documents left in it,
* AND the shard returning DONE with that skip.
* Because of this, this problem didn't occur in 3.5, as the UnsortingGather dependencies were always RemoteNodes,
* and the RemoteNodes always reported HASMORE when at least one document was skipped.
* If we just used EnumerateCollection, the RocksDB iterator would also report HASMORE with the last document.
* Thus we use a FILTER here, which overfetches - the test relies on this and will not work without it, but I see
* no other way without writing a plan manually.
*/
testSkipExactDocsInShard: function () {
const query = 'FOR doc IN @@col FILTER doc._key != "" LIMIT 1, null RETURN doc';
const bind = {'@col': colName};
for (let i = 0; i < 2*numberOfShards; ++i) {
col.insert({});
const res = db._query(query, bind);
const n = res.toArray().length;
assertEqual(i, n);
}
},
};
}
jsunity.run(aqlSkippingClusterTestsuite);
return jsunity.done();