mirror of https://gitee.com/bigwinds/arangodb
406 lines
12 KiB
JavaScript
406 lines
12 KiB
JavaScript
/* jshint strict: false */
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Foxx administration actions
|
|
// /
|
|
// / @file
|
|
// /
|
|
// / DISCLAIMER
|
|
// /
|
|
// / Copyright 2016 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 Dr. Frank Celler
|
|
// / @author Copyright 2014-2016, ArangoDB GmbH, Cologne, Germany
|
|
// / @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
const actions = require('@arangodb/actions');
|
|
const FoxxManager = require('@arangodb/foxx/manager');
|
|
const store = require('@arangodb/foxx/store');
|
|
const request = require('@arangodb/request');
|
|
const db = require('@arangodb').db;
|
|
const ArangoError = require('@arangodb').ArangoError;
|
|
const joinPath = require('path').join;
|
|
const fs = require('fs');
|
|
const fmu = require('@arangodb/foxx/manager-utils');
|
|
|
|
const easyPostCallback = actions.easyPostCallback;
|
|
|
|
function proxyLocal (method, url, qs, body, headers = {}) {
|
|
url = `/_db/${db._name()}${url}`;
|
|
if (body instanceof Buffer) {
|
|
if (body.utf8Slice(0, 4) === 'PK\u0003\u0004') {
|
|
headers['content-type'] = 'application/zip';
|
|
} else {
|
|
headers['content-type'] = 'application/javascript';
|
|
}
|
|
} else if (body && typeof body === 'object') {
|
|
headers['content-type'] = 'application/json';
|
|
body = JSON.stringify(body);
|
|
}
|
|
if (body) {
|
|
headers['content-length'] = body.length;
|
|
}
|
|
const req = {
|
|
method,
|
|
url,
|
|
qs,
|
|
headers,
|
|
body
|
|
};
|
|
if (require('internal').db._version(true)['maintainer-mode'] === 'true') {
|
|
req.timeout = 300;
|
|
}
|
|
const res = request(req);
|
|
if (res.json && res.json.errorNum) {
|
|
throw new ArangoError(res.json);
|
|
}
|
|
res.throw();
|
|
return res.body ? JSON.parse(res.body) : null;
|
|
}
|
|
|
|
function resolveAppInfo (appInfo, refresh) {
|
|
if (!appInfo || typeof appInfo !== 'string') {
|
|
return appInfo;
|
|
}
|
|
if (/^git:/i.test(appInfo)) {
|
|
const splitted = appInfo.split(':');
|
|
const baseUrl = process.env.FOXX_BASE_URL || 'https://github.com/';
|
|
return {source: `${baseUrl}${splitted[1]}/archive/${splitted[2] || 'master'}.zip`};
|
|
}
|
|
if (/^https?:/i.test(appInfo)) {
|
|
return {source: appInfo};
|
|
}
|
|
if (/^uploads[/\\]tmp-/.test(appInfo)) {
|
|
const tempFile = joinPath(fs.getTempPath(), appInfo);
|
|
const buffer = fs.readFileSync(tempFile);
|
|
try {
|
|
fs.remove(tempFile);
|
|
} catch (e) {
|
|
console.warnStack(e, `Failed to remove uploaded file: ${tempFile}`);
|
|
}
|
|
return buffer;
|
|
}
|
|
if (fs.isDirectory(appInfo)) {
|
|
const tempFile = fmu.zipDirectory(appInfo);
|
|
const buffer = fs.readFileSync(tempFile);
|
|
try {
|
|
fs.removeDirectoryRecursive(tempFile);
|
|
} catch (e) {
|
|
console.warnStack(e, `Failed to remove temporary file: ${tempFile}`);
|
|
}
|
|
return buffer;
|
|
}
|
|
if (fs.exists(appInfo)) {
|
|
return fs.readFileSync(appInfo);
|
|
}
|
|
if (refresh !== false) {
|
|
try {
|
|
store.update();
|
|
} catch (e) {
|
|
console.warnStack(e);
|
|
}
|
|
}
|
|
return {source: appInfo};
|
|
}
|
|
|
|
// disable foxx manager routes / foxx-cli when foxx api is disabled
|
|
if (!require("internal").isFoxxApiDisabled()) {
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief sets up a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/setup',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
|
|
return FoxxManager.setup(mount);
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief tears down a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/teardown',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
|
|
return FoxxManager.teardown(mount);
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief installs a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/install',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
const options = body.options || {};
|
|
const appInfo = resolveAppInfo(body.appInfo, options.refresh);
|
|
options.mount = mount;
|
|
proxyLocal('POST', '/_api/foxx', options, appInfo, req.headers);
|
|
return FoxxManager.lookupService(mount).simpleJSON();
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief uninstalls a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/uninstall',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
const options = body.options || {};
|
|
options.mount = mount;
|
|
proxyLocal('DELETE', '/_api/foxx/service', options, undefined, req.headers);
|
|
return {mount};
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief replaces a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/replace',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
const options = body.options || {};
|
|
const appInfo = resolveAppInfo(body.appInfo, options.refresh);
|
|
options.mount = mount;
|
|
proxyLocal('PUT', '/_api/foxx/service', options, appInfo, req.headers);
|
|
return FoxxManager.lookupService(mount).simpleJSON();
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief upgrades a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/upgrade',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
const options = body.options || {};
|
|
const appInfo = resolveAppInfo(body.appInfo, options.refresh);
|
|
options.mount = mount;
|
|
proxyLocal('PATCH', '/_api/foxx/service', options, appInfo, req.headers);
|
|
return FoxxManager.lookupService(mount).simpleJSON();
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief configures a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/configure',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
let options = body.options;
|
|
if (options && options.configuration) {
|
|
options = options.configuration;
|
|
}
|
|
proxyLocal('PUT', '/_api/foxx/configuration', {mount}, options, req.headers);
|
|
return FoxxManager.lookupService(mount).simpleJSON();
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Gets the configuration of a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/configuration',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
return FoxxManager.configuration(mount);
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief configures a Foxx service's dependencies
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/set-dependencies',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
let options = body.options;
|
|
if (options && options.dependencies) {
|
|
options = options.dependencies;
|
|
}
|
|
proxyLocal('PUT', '/_api/foxx/dependencies', {mount}, options, req.headers);
|
|
return FoxxManager.lookupService(mount).simpleJSON();
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Gets the dependencies of a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/dependencies',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
|
|
const deps = FoxxManager.dependencies(mount);
|
|
for (const key of Object.keys(deps)) {
|
|
const dep = deps[key];
|
|
deps[key] = {
|
|
definition: dep,
|
|
title: dep.title,
|
|
current: dep.current
|
|
};
|
|
delete dep.title;
|
|
delete dep.current;
|
|
}
|
|
return deps;
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Toggles the development mode of a Foxx service
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/development',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
const activate = body.activate;
|
|
if (activate) {
|
|
return FoxxManager.development(mount).simpleJSON();
|
|
} else {
|
|
return FoxxManager.production(mount).simpleJSON();
|
|
}
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Run tests for an app
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/tests',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const mount = body.mount;
|
|
const options = body.options;
|
|
return FoxxManager.runTests(mount, options);
|
|
}
|
|
})
|
|
});
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Run script for an app
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
actions.defineHttp({
|
|
url: '_admin/foxx/script',
|
|
prefix: false,
|
|
isSystem: true,
|
|
|
|
callback: easyPostCallback({
|
|
body: true,
|
|
callback: function (body, req) {
|
|
const name = body.name;
|
|
const mount = body.mount;
|
|
const options = body.options;
|
|
return FoxxManager.runScript(name, mount, options);
|
|
}
|
|
})
|
|
});
|
|
|
|
} // end - if not foxx api disabled
|