mirror of https://gitee.com/bigwinds/arangodb
Better Foxx API error handling
This commit is contained in:
parent
d28a14da24
commit
c0a3f5a8a1
|
@ -5,6 +5,9 @@ const fs = require('fs');
|
||||||
const joi = require('joi');
|
const joi = require('joi');
|
||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
|
|
||||||
|
const actions = require('@arangodb/actions');
|
||||||
|
const ArangoError = require('@arangodb').ArangoError;
|
||||||
|
const errors = require('@arangodb').errors;
|
||||||
const fm = require('@arangodb/foxx/manager');
|
const fm = require('@arangodb/foxx/manager');
|
||||||
const fmu = require('@arangodb/foxx/manager-utils');
|
const fmu = require('@arangodb/foxx/manager-utils');
|
||||||
const createRouter = require('@arangodb/foxx/router');
|
const createRouter = require('@arangodb/foxx/router');
|
||||||
|
@ -15,6 +18,12 @@ const router = createRouter();
|
||||||
module.context.registerType('multipart/form-data', require('./multipart'));
|
module.context.registerType('multipart/form-data', require('./multipart'));
|
||||||
module.context.use(router);
|
module.context.use(router);
|
||||||
|
|
||||||
|
const legacyErrors = new Map([
|
||||||
|
[errors.ERROR_SERVICE_INVALID_NAME.code, errors.ERROR_FOXX_SOURCE_NOT_FOUND.code],
|
||||||
|
[errors.ERROR_SERVICE_INVALID_MOUNT.code, errors.ERROR_INVALID_MOUNTPOINT.code],
|
||||||
|
[errors.ERROR_SERVICE_DOWNLOAD_FAILED.code, errors.ERROR_FOXX_SOURCE_ERROR.code],
|
||||||
|
[errors.ERROR_SERVICE_UPLOAD_FAILED.code, errors.ERROR_FOXX_SOURCE_ERROR.code]
|
||||||
|
]);
|
||||||
|
|
||||||
const serviceToJson = (service) => (
|
const serviceToJson = (service) => (
|
||||||
{
|
{
|
||||||
|
@ -40,6 +49,41 @@ function writeUploadToTempFile (buffer) {
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function prepareServiceRequestBody (req, res, next) {
|
||||||
|
if (req.body.source instanceof Buffer) {
|
||||||
|
req.body.source = writeUploadToTempFile(req.body.source);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (req.body.dependencies) {
|
||||||
|
req.body.dependencies = JSON.parse(req.body.dependencies);
|
||||||
|
}
|
||||||
|
if (req.body.configuration) {
|
||||||
|
req.body.configuration = JSON.parse(req.body.configuration);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
throw new ArangoError({
|
||||||
|
errorNum: errors.ERROR_SERVICE_OPTIONS_MALFORMED.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_OPTIONS_MALFORMED.message}
|
||||||
|
Details: ${e.message}
|
||||||
|
`
|
||||||
|
}, {cause: e});
|
||||||
|
}
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
router.use((req, res, next) => {
|
||||||
|
try {
|
||||||
|
next();
|
||||||
|
} catch (e) {
|
||||||
|
if (e.isArangoError) {
|
||||||
|
const errorNum = legacyErrors.get(e.errorNum) || e.errorNum;
|
||||||
|
const status = actions.arangoErrorToHttpCode(errorNum);
|
||||||
|
res.throw(status, e.errorMessage, {errorNum, cause: e});
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
router.get((req, res) => {
|
router.get((req, res) => {
|
||||||
res.json(
|
res.json(
|
||||||
|
@ -49,6 +93,7 @@ router.get((req, res) => {
|
||||||
mount: service.mount,
|
mount: service.mount,
|
||||||
name: service.manifest.name,
|
name: service.manifest.name,
|
||||||
version: service.manifest.version,
|
version: service.manifest.version,
|
||||||
|
provides: service.manifest.provides || {},
|
||||||
development: service.isDevelopment,
|
development: service.isDevelopment,
|
||||||
legacy: isLegacy(service)
|
legacy: isLegacy(service)
|
||||||
}
|
}
|
||||||
|
@ -61,21 +106,14 @@ router.get((req, res) => {
|
||||||
Fetches a list of services installed in the current database.
|
Fetches a list of services installed in the current database.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
router.post(prepareServiceRequestBody, (req, res) => {
|
||||||
router.post((req, res) => {
|
|
||||||
let source = req.body.source;
|
|
||||||
if (source instanceof Buffer) {
|
|
||||||
source = writeUploadToTempFile(source);
|
|
||||||
}
|
|
||||||
const dependencies = req.body.dependencies && JSON.parse(req.body.dependencies);
|
|
||||||
const configuration = req.body.configuration && JSON.parse(req.body.configuration);
|
|
||||||
const mount = req.queryParams.mount;
|
const mount = req.queryParams.mount;
|
||||||
fm.install(source, mount, _.omit(req.queryParams, ['mount']));
|
fm.install(req.body.source, mount, _.omit(req.queryParams, ['mount']));
|
||||||
if (configuration) {
|
if (req.body.configuration) {
|
||||||
fm.setConfiguration(mount, {configuration, replace: true});
|
fm.setConfiguration(mount, {configuration: req.body.configuration, replace: true});
|
||||||
}
|
}
|
||||||
if (dependencies) {
|
if (req.body.dependencies) {
|
||||||
fm.setDependencies(mount, {dependencies, replace: true});
|
fm.setDependencies(mount, {dependencies: req.body.dependencies, replace: true});
|
||||||
}
|
}
|
||||||
const service = fm.lookupService(mount);
|
const service = fm.lookupService(mount);
|
||||||
res.json(serviceToJson(service));
|
res.json(serviceToJson(service));
|
||||||
|
@ -94,7 +132,6 @@ router.post((req, res) => {
|
||||||
or as a binary zip file using multipart form upload.
|
or as a binary zip file using multipart form upload.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
const instanceRouter = createRouter();
|
const instanceRouter = createRouter();
|
||||||
instanceRouter.use((req, res, next) => {
|
instanceRouter.use((req, res, next) => {
|
||||||
const mount = req.queryParams.mount;
|
const mount = req.queryParams.mount;
|
||||||
|
@ -108,7 +145,6 @@ instanceRouter.use((req, res, next) => {
|
||||||
.queryParam('mount', schemas.mount, `Mount path of the installed service.`);
|
.queryParam('mount', schemas.mount, `Mount path of the installed service.`);
|
||||||
router.use(instanceRouter);
|
router.use(instanceRouter);
|
||||||
|
|
||||||
|
|
||||||
const serviceRouter = createRouter();
|
const serviceRouter = createRouter();
|
||||||
instanceRouter.use('/service', serviceRouter);
|
instanceRouter.use('/service', serviceRouter);
|
||||||
|
|
||||||
|
@ -121,21 +157,14 @@ serviceRouter.get((req, res) => {
|
||||||
Fetches detailed information for the service at the given mount path.
|
Fetches detailed information for the service at the given mount path.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
serviceRouter.patch(prepareServiceRequestBody, (req, res) => {
|
||||||
serviceRouter.patch((req, res) => {
|
|
||||||
let source = req.body.source;
|
|
||||||
if (source instanceof Buffer) {
|
|
||||||
source = writeUploadToTempFile(source);
|
|
||||||
}
|
|
||||||
const dependencies = req.body.dependencies && JSON.parse(req.body.dependencies);
|
|
||||||
const configuration = req.body.configuration && JSON.parse(req.body.configuration);
|
|
||||||
const mount = req.queryParams.mount;
|
const mount = req.queryParams.mount;
|
||||||
fm.upgrade(source, mount, _.omit(req.queryParams, ['mount']));
|
fm.upgrade(req.body.source, mount, _.omit(req.queryParams, ['mount']));
|
||||||
if (configuration) {
|
if (req.body.configuration) {
|
||||||
fm.setConfiguration(mount, {configuration, replace: false});
|
fm.setConfiguration(mount, {configuration: req.body.configuration, replace: false});
|
||||||
}
|
}
|
||||||
if (dependencies) {
|
if (req.body.dependencies) {
|
||||||
fm.setDependencies(mount, {dependencies, replace: false});
|
fm.setDependencies(mount, {dependencies: req.body.dependencies, replace: false});
|
||||||
}
|
}
|
||||||
const service = fm.lookupService(mount);
|
const service = fm.lookupService(mount);
|
||||||
res.json(serviceToJson(service));
|
res.json(serviceToJson(service));
|
||||||
|
@ -155,21 +184,14 @@ serviceRouter.patch((req, res) => {
|
||||||
or as a binary zip file using multipart form upload.
|
or as a binary zip file using multipart form upload.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
serviceRouter.put(prepareServiceRequestBody, (req, res) => {
|
||||||
serviceRouter.put((req, res) => {
|
|
||||||
let source = req.body.source;
|
|
||||||
if (source instanceof Buffer) {
|
|
||||||
source = writeUploadToTempFile(source);
|
|
||||||
}
|
|
||||||
const dependencies = req.body.dependencies && JSON.parse(req.body.dependencies);
|
|
||||||
const configuration = req.body.configuration && JSON.parse(req.body.configuration);
|
|
||||||
const mount = req.queryParams.mount;
|
const mount = req.queryParams.mount;
|
||||||
fm.replace(source, mount, _.omit(req.queryParams, ['mount']));
|
fm.replace(req.body.source, mount, _.omit(req.queryParams, ['mount']));
|
||||||
if (configuration) {
|
if (req.body.configuration) {
|
||||||
fm.setConfiguration(mount, {configuration, replace: true});
|
fm.setConfiguration(mount, {configuration: req.body.configuration, replace: true});
|
||||||
}
|
}
|
||||||
if (dependencies) {
|
if (req.body.dependencies) {
|
||||||
fm.setDependencies(mount, {dependencies, replace: true});
|
fm.setDependencies(mount, {dependencies: req.body.dependencies, replace: true});
|
||||||
}
|
}
|
||||||
const service = fm.lookupService(mount);
|
const service = fm.lookupService(mount);
|
||||||
res.json(serviceToJson(service));
|
res.json(serviceToJson(service));
|
||||||
|
@ -189,7 +211,6 @@ serviceRouter.put((req, res) => {
|
||||||
or as a binary zip file using multipart form upload.
|
or as a binary zip file using multipart form upload.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
serviceRouter.delete((req, res) => {
|
serviceRouter.delete((req, res) => {
|
||||||
fm.uninstall(
|
fm.uninstall(
|
||||||
req.queryParams.mount,
|
req.queryParams.mount,
|
||||||
|
@ -204,7 +225,6 @@ serviceRouter.delete((req, res) => {
|
||||||
Removes the service at the given mount path from the database and file system.
|
Removes the service at the given mount path from the database and file system.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
const configRouter = createRouter();
|
const configRouter = createRouter();
|
||||||
instanceRouter.use('/configuration', configRouter)
|
instanceRouter.use('/configuration', configRouter)
|
||||||
.response(200, schemas.configs, `Configuration options of the service.`);
|
.response(200, schemas.configs, `Configuration options of the service.`);
|
||||||
|
@ -247,7 +267,6 @@ configRouter.put((req, res) => {
|
||||||
Any omitted options will be reset to their default values or marked as unconfigured.
|
Any omitted options will be reset to their default values or marked as unconfigured.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
const depsRouter = createRouter();
|
const depsRouter = createRouter();
|
||||||
instanceRouter.use('/dependencies', depsRouter)
|
instanceRouter.use('/dependencies', depsRouter)
|
||||||
.response(200, schemas.deps, `Dependency options of the service.`);
|
.response(200, schemas.deps, `Dependency options of the service.`);
|
||||||
|
@ -290,7 +309,6 @@ depsRouter.put((req, res) => {
|
||||||
Any omitted dependencies will be disabled.
|
Any omitted dependencies will be disabled.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
const devRouter = createRouter();
|
const devRouter = createRouter();
|
||||||
instanceRouter.use('/development', devRouter)
|
instanceRouter.use('/development', devRouter)
|
||||||
.response(200, schemas.fullInfo, `Description of the service.`);
|
.response(200, schemas.fullInfo, `Description of the service.`);
|
||||||
|
@ -315,7 +333,6 @@ devRouter.delete((req, res) => {
|
||||||
Changes to the service's code will no longer be reflected automatically.
|
Changes to the service's code will no longer be reflected automatically.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
const scriptsRouter = createRouter();
|
const scriptsRouter = createRouter();
|
||||||
instanceRouter.use('/scripts', scriptsRouter);
|
instanceRouter.use('/scripts', scriptsRouter);
|
||||||
|
|
||||||
|
@ -345,7 +362,6 @@ scriptsRouter.post('/:name', (req, res) => {
|
||||||
Returns the exports of the script, if any.
|
Returns the exports of the script, if any.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
instanceRouter.post('/tests', (req, res) => {
|
instanceRouter.post('/tests', (req, res) => {
|
||||||
const service = req.service;
|
const service = req.service;
|
||||||
const reporter = req.queryParams.reporter || null;
|
const reporter = req.queryParams.reporter || null;
|
||||||
|
@ -358,7 +374,6 @@ instanceRouter.post('/tests', (req, res) => {
|
||||||
Runs the tests for the service at the given mount path and returns the results.
|
Runs the tests for the service at the given mount path and returns the results.
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
|
||||||
instanceRouter.get('/readme', (req, res) => {
|
instanceRouter.get('/readme', (req, res) => {
|
||||||
const service = req.service;
|
const service = req.service;
|
||||||
res.send(fm.readme(service.mount));
|
res.send(fm.readme(service.mount));
|
||||||
|
|
|
@ -250,13 +250,17 @@
|
||||||
"SIMPLE_CLIENT_COULD_NOT_WRITE" : { "code" : 2002, "message" : "could not write to server" },
|
"SIMPLE_CLIENT_COULD_NOT_WRITE" : { "code" : 2002, "message" : "could not write to server" },
|
||||||
"SIMPLE_CLIENT_COULD_NOT_READ" : { "code" : 2003, "message" : "could not read from server" },
|
"SIMPLE_CLIENT_COULD_NOT_READ" : { "code" : 2003, "message" : "could not read from server" },
|
||||||
"COMMUNICATOR_REQUEST_ABORTED" : { "code" : 2100, "message" : "Request aborted" },
|
"COMMUNICATOR_REQUEST_ABORTED" : { "code" : 2100, "message" : "Request aborted" },
|
||||||
"ERROR_MALFORMED_MANIFEST_FILE" : { "code" : 3000, "message" : "malformed manifest file" },
|
"ERROR_MALFORMED_MANIFEST_FILE" : { "code" : 3000, "message" : "failed to parse manifest file" },
|
||||||
"ERROR_INVALID_SERVICE_MANIFEST" : { "code" : 3001, "message" : "manifest file is invalid" },
|
"ERROR_INVALID_SERVICE_MANIFEST" : { "code" : 3001, "message" : "manifest file is invalid" },
|
||||||
"ERROR_INVALID_FOXX_OPTIONS" : { "code" : 3004, "message" : "invalid foxx options" },
|
"ERROR_INVALID_FOXX_OPTIONS" : { "code" : 3004, "message" : "service options are invalid" },
|
||||||
"ERROR_INVALID_MOUNTPOINT" : { "code" : 3007, "message" : "mountpoint is invalid" },
|
"ERROR_INVALID_MOUNTPOINT" : { "code" : 3007, "message" : "invalid mountpath" },
|
||||||
"ERROR_SERVICE_NOT_FOUND" : { "code" : 3009, "message" : "Service not found" },
|
"ERROR_SERVICE_NOT_FOUND" : { "code" : 3009, "message" : "service not found" },
|
||||||
"ERROR_SERVICE_NEEDS_CONFIGURATION" : { "code" : 3010, "message" : "Service not configured" },
|
"ERROR_SERVICE_NEEDS_CONFIGURATION" : { "code" : 3010, "message" : "service needs configuration" },
|
||||||
"ERROR_SERVICE_MOUNTPOINT_CONFLICT" : { "code" : 3011, "message" : "mountpoint already in use" },
|
"ERROR_SERVICE_MOUNTPOINT_CONFLICT" : { "code" : 3011, "message" : "service already exists" },
|
||||||
|
"ERROR_FOXX_MANIFEST_NOT_FOUND" : { "code" : 3012, "message" : "missing manifest file" },
|
||||||
|
"ERROR_FOXX_OPTIONS_MALFORMED" : { "code" : 3013, "message" : "failed to parse service options" },
|
||||||
|
"ERROR_FOXX_SOURCE_NOT_FOUND" : { "code" : 3014, "message" : "source path not found" },
|
||||||
|
"ERROR_FOXX_SOURCE_ERROR" : { "code" : 3015, "message" : "error resolving source" },
|
||||||
"ERROR_MODULE_NOT_FOUND" : { "code" : 3100, "message" : "cannot locate module" },
|
"ERROR_MODULE_NOT_FOUND" : { "code" : 3100, "message" : "cannot locate module" },
|
||||||
"ERROR_MODULE_FAILURE" : { "code" : 3103, "message" : "failed to invoke module" },
|
"ERROR_MODULE_FAILURE" : { "code" : 3103, "message" : "failed to invoke module" },
|
||||||
"ERROR_NO_SMART_COLLECTION" : { "code" : 4000, "message" : "collection is not smart" },
|
"ERROR_NO_SMART_COLLECTION" : { "code" : 4000, "message" : "collection is not smart" },
|
||||||
|
|
|
@ -1801,6 +1801,7 @@ function arangoErrorToHttpCode (num) {
|
||||||
case arangodb.ERROR_USER_NOT_FOUND:
|
case arangodb.ERROR_USER_NOT_FOUND:
|
||||||
case arangodb.ERROR_TASK_NOT_FOUND:
|
case arangodb.ERROR_TASK_NOT_FOUND:
|
||||||
case arangodb.ERROR_QUERY_NOT_FOUND:
|
case arangodb.ERROR_QUERY_NOT_FOUND:
|
||||||
|
case arangodb.ERROR_SERVICE_NOT_FOUND:
|
||||||
return exports.HTTP_NOT_FOUND;
|
return exports.HTTP_NOT_FOUND;
|
||||||
|
|
||||||
case arangodb.ERROR_REQUEST_CANCELED:
|
case arangodb.ERROR_REQUEST_CANCELED:
|
||||||
|
@ -1808,6 +1809,7 @@ function arangoErrorToHttpCode (num) {
|
||||||
|
|
||||||
case arangodb.ERROR_ARANGO_DUPLICATE_NAME:
|
case arangodb.ERROR_ARANGO_DUPLICATE_NAME:
|
||||||
case arangodb.ERROR_ARANGO_DUPLICATE_IDENTIFIER:
|
case arangodb.ERROR_ARANGO_DUPLICATE_IDENTIFIER:
|
||||||
|
case arangodb.ERROR_SERVICE_MOUNTPOINT_CONFLICT:
|
||||||
return exports.HTTP_CONFLICT;
|
return exports.HTTP_CONFLICT;
|
||||||
|
|
||||||
case arangodb.ERROR_CLUSTER_UNSUPPORTED:
|
case arangodb.ERROR_CLUSTER_UNSUPPORTED:
|
||||||
|
|
|
@ -55,9 +55,6 @@ const executeGlobalContextFunction = require('internal').executeGlobalContextFun
|
||||||
const actions = require('@arangodb/actions');
|
const actions = require('@arangodb/actions');
|
||||||
const plainServerVersion = require('@arangodb').plainServerVersion;
|
const plainServerVersion = require('@arangodb').plainServerVersion;
|
||||||
|
|
||||||
const throwDownloadError = arangodb.throwDownloadError;
|
|
||||||
const throwFileNotFound = arangodb.throwFileNotFound;
|
|
||||||
|
|
||||||
// Regular expressions for joi patterns
|
// Regular expressions for joi patterns
|
||||||
const RE_EMPTY = /^$/;
|
const RE_EMPTY = /^$/;
|
||||||
const RE_NOT_EMPTY = /./;
|
const RE_NOT_EMPTY = /./;
|
||||||
|
@ -472,7 +469,13 @@ function checkManifest (filename, inputManifest, mount, isDevelopment) {
|
||||||
function validateManifestFile (filename, mount, isDevelopment) {
|
function validateManifestFile (filename, mount, isDevelopment) {
|
||||||
let mf;
|
let mf;
|
||||||
if (!fs.exists(filename)) {
|
if (!fs.exists(filename)) {
|
||||||
throwFileNotFound(`Cannot find manifest file "${filename}"`);
|
throw new ArangoError({
|
||||||
|
errorNum: errors.ERROR_SERVICE_MANIFEST_NOT_FOUND.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_MANIFEST_NOT_FOUND.message}
|
||||||
|
File: ${filename}
|
||||||
|
`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mf = JSON.parse(fs.read(filename));
|
mf = JSON.parse(fs.read(filename));
|
||||||
|
@ -713,7 +716,13 @@ function extractServiceToPath (archive, targetPath, noDelete) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found === undefined) {
|
if (found === undefined) {
|
||||||
throwFileNotFound(`Cannot find manifest file in zip file "${tempFile}"`);
|
throw new ArangoError({
|
||||||
|
errorNum: errors.ERROR_SERVICE_MANIFEST_NOT_FOUND.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_MANIFEST_NOT_FOUND.message}
|
||||||
|
Source: ${tempFile}
|
||||||
|
`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var mp;
|
var mp;
|
||||||
|
@ -786,11 +795,23 @@ function installServiceFromRemote (url, targetPath) {
|
||||||
}, tempFile);
|
}, tempFile);
|
||||||
|
|
||||||
if (result.code < 200 || result.code > 299) {
|
if (result.code < 200 || result.code > 299) {
|
||||||
throwDownloadError(`Could not download from "${url}"`);
|
throw new ArangoError({
|
||||||
|
errorNum: errors.ERROR_SERVICE_SOURCE_ERROR.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_SOURCE_ERROR.message}
|
||||||
|
URL: ${url}
|
||||||
|
Status: ${result.code}
|
||||||
|
`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (e) {
|
||||||
let details = String(err.stack || err);
|
throw new ArangoError({
|
||||||
throwDownloadError(`Could not download from "${url}": ${details}`);
|
errorNum: errors.ERROR_SERVICE_SOURCE_ERROR.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_SOURCE_ERROR.message}
|
||||||
|
URL: ${url}
|
||||||
|
`
|
||||||
|
}, {cause: e});
|
||||||
}
|
}
|
||||||
extractServiceToPath(tempFile, targetPath);
|
extractServiceToPath(tempFile, targetPath);
|
||||||
}
|
}
|
||||||
|
@ -829,6 +850,15 @@ function isLocalFile (path) {
|
||||||
// //////////////////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
function installServiceFromLocal (path, targetPath) {
|
function installServiceFromLocal (path, targetPath) {
|
||||||
|
if (!fs.exists(path)) {
|
||||||
|
throw new ArangoError({
|
||||||
|
errorNum: errors.ERROR_SERVICE_SOURCE_NOT_FOUND.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_SOURCE_NOT_FOUND.message}
|
||||||
|
Path: ${path}
|
||||||
|
`
|
||||||
|
});
|
||||||
|
}
|
||||||
if (fs.isDirectory(path)) {
|
if (fs.isDirectory(path)) {
|
||||||
extractServiceToPath(utils.zipDirectory(path), targetPath);
|
extractServiceToPath(utils.zipDirectory(path), targetPath);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -31,6 +31,8 @@ const Module = require('module');
|
||||||
const semver = require('semver');
|
const semver = require('semver');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const ArangoError = require('@arangodb').ArangoError;
|
||||||
|
const errors = require('@arangodb').errors;
|
||||||
const defaultTypes = require('@arangodb/foxx/types');
|
const defaultTypes = require('@arangodb/foxx/types');
|
||||||
const FoxxContext = require('@arangodb/foxx/context');
|
const FoxxContext = require('@arangodb/foxx/context');
|
||||||
const parameterTypes = require('@arangodb/foxx/manager-utils').parameterTypes;
|
const parameterTypes = require('@arangodb/foxx/manager-utils').parameterTypes;
|
||||||
|
@ -440,8 +442,17 @@ module.exports =
|
||||||
executeScript (name, argv) {
|
executeScript (name, argv) {
|
||||||
var scripts = this.manifest.scripts;
|
var scripts = this.manifest.scripts;
|
||||||
// Only run setup/teardown scripts if they exist
|
// Only run setup/teardown scripts if they exist
|
||||||
if (!scripts[name] && (name === 'setup' || name === 'teardown')) {
|
if (!scripts[name]) {
|
||||||
return undefined;
|
if (name === 'setup' || name === 'teardown') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
throw new ArangoError({
|
||||||
|
errorNum: errors.ERROR_SERVICE_UNKNOWN_SCRIPT.code,
|
||||||
|
errorMessage: dd`
|
||||||
|
${errors.ERROR_SERVICE_UNKNOWN_SCRIPT.message}
|
||||||
|
Name: ${name}
|
||||||
|
`
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return this.run(scripts[name], {
|
return this.run(scripts[name], {
|
||||||
foxxContext: {
|
foxxContext: {
|
||||||
|
|
|
@ -273,7 +273,8 @@ ERROR_USER_NOT_FOUND,1703,"user not found","Will be raised when a user name is u
|
||||||
ERROR_USER_CHANGE_PASSWORD,1704,"user must change his password","Will be raised when the user must change his password."
|
ERROR_USER_CHANGE_PASSWORD,1704,"user must change his password","Will be raised when the user must change his password."
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
## Service management errors
|
## Service management errors (legacy)
|
||||||
|
## These have been superceded by the Foxx management errors in public APIs.
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
ERROR_SERVICE_INVALID_NAME,1750,"invalid service name","Will be raised when an invalid service name is specified."
|
ERROR_SERVICE_INVALID_NAME,1750,"invalid service name","Will be raised when an invalid service name is specified."
|
||||||
|
@ -344,19 +345,25 @@ SIMPLE_CLIENT_COULD_NOT_READ,2003,"could not read from server","Will be raised w
|
||||||
################################################################################
|
################################################################################
|
||||||
## Communicator errors
|
## Communicator errors
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
COMMUNICATOR_REQUEST_ABORTED,2100,"Request aborted", "Request was aborted."
|
COMMUNICATOR_REQUEST_ABORTED,2100,"Request aborted", "Request was aborted."
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
## Foxx Manager errors
|
## Foxx management errors
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
ERROR_MALFORMED_MANIFEST_FILE,3000,"malformed manifest file","The manifest file is malformed. It is not in a valid JSON format."
|
ERROR_MALFORMED_MANIFEST_FILE,3000,"failed to parse manifest file","The service manifest file is not well-formed JSON."
|
||||||
ERROR_INVALID_SERVICE_MANIFEST,3001,"manifest file is invalid","The manifest file of this service is invalid."
|
ERROR_INVALID_SERVICE_MANIFEST,3001,"manifest file is invalid","The service manifest contains invalid values."
|
||||||
ERROR_INVALID_FOXX_OPTIONS,3004,"invalid foxx options","The options used to configure the foxx are invalid."
|
ERROR_INVALID_FOXX_OPTIONS,3004,"service options are invalid","The service options contain invalid values."
|
||||||
ERROR_INVALID_MOUNTPOINT,3007,"mountpoint is invalid","mountpoint is invalid"
|
ERROR_INVALID_MOUNTPOINT,3007,"invalid mountpath","The service mountpath contains invalid characters."
|
||||||
ERROR_SERVICE_NOT_FOUND,3009,"Service not found","No service found at this mountpoint"
|
ERROR_SERVICE_NOT_FOUND,3009,"service not found","No service found at the given mountpath."
|
||||||
ERROR_SERVICE_NEEDS_CONFIGURATION,3010,"Service not configured","The service has to be configured before it can be used"
|
ERROR_SERVICE_NEEDS_CONFIGURATION,3010,"service needs configuration","The service is missing configuration or dependencies."
|
||||||
ERROR_SERVICE_MOUNTPOINT_CONFLICT,3011,"mountpoint already in use","A service has already been installed at this mountpoint"
|
ERROR_SERVICE_MOUNTPOINT_CONFLICT,3011,"service already exists","A service already exists at the given mountpath."
|
||||||
|
ERROR_SERVICE_MANIFEST_NOT_FOUND,3012,"missing manifest file","The service directory does not contain a manifest file."
|
||||||
|
ERROR_SERVICE_OPTIONS_MALFORMED,3013,"failed to parse service options","The service options are not well-formed JSON."
|
||||||
|
ERROR_SERVICE_SOURCE_NOT_FOUND,3014,"source path not found","The source path does not match a file or directory."
|
||||||
|
ERROR_SERVICE_SOURCE_ERROR,3015,"error resolving source","The source path could not be resolved."
|
||||||
|
ERROR_SERVICE_UNKNOWN_SCRIPT,3016,"unknown script","The service does not have a script with this name."
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
## JavaScript module loader errors
|
## JavaScript module loader errors
|
||||||
|
@ -365,7 +372,6 @@ ERROR_SERVICE_MOUNTPOINT_CONFLICT,3011,"mountpoint already in use","A service ha
|
||||||
ERROR_MODULE_NOT_FOUND,3100,"cannot locate module","The module path could not be resolved."
|
ERROR_MODULE_NOT_FOUND,3100,"cannot locate module","The module path could not be resolved."
|
||||||
ERROR_MODULE_FAILURE,3103,"failed to invoke module","Failed to invoke the module in its context."
|
ERROR_MODULE_FAILURE,3103,"failed to invoke module","Failed to invoke the module in its context."
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
## Enterprise errors
|
## Enterprise errors
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
|
@ -246,13 +246,17 @@ void TRI_InitializeErrorMessages () {
|
||||||
REG_ERROR(SIMPLE_CLIENT_COULD_NOT_WRITE, "could not write to server");
|
REG_ERROR(SIMPLE_CLIENT_COULD_NOT_WRITE, "could not write to server");
|
||||||
REG_ERROR(SIMPLE_CLIENT_COULD_NOT_READ, "could not read from server");
|
REG_ERROR(SIMPLE_CLIENT_COULD_NOT_READ, "could not read from server");
|
||||||
REG_ERROR(COMMUNICATOR_REQUEST_ABORTED, "Request aborted");
|
REG_ERROR(COMMUNICATOR_REQUEST_ABORTED, "Request aborted");
|
||||||
REG_ERROR(ERROR_MALFORMED_MANIFEST_FILE, "malformed manifest file");
|
REG_ERROR(ERROR_MALFORMED_MANIFEST_FILE, "failed to parse manifest file");
|
||||||
REG_ERROR(ERROR_INVALID_SERVICE_MANIFEST, "manifest file is invalid");
|
REG_ERROR(ERROR_INVALID_SERVICE_MANIFEST, "manifest file is invalid");
|
||||||
REG_ERROR(ERROR_INVALID_FOXX_OPTIONS, "invalid foxx options");
|
REG_ERROR(ERROR_INVALID_FOXX_OPTIONS, "service options are invalid");
|
||||||
REG_ERROR(ERROR_INVALID_MOUNTPOINT, "mountpoint is invalid");
|
REG_ERROR(ERROR_INVALID_MOUNTPOINT, "invalid mountpath");
|
||||||
REG_ERROR(ERROR_SERVICE_NOT_FOUND, "Service not found");
|
REG_ERROR(ERROR_SERVICE_NOT_FOUND, "service not found");
|
||||||
REG_ERROR(ERROR_SERVICE_NEEDS_CONFIGURATION, "Service not configured");
|
REG_ERROR(ERROR_SERVICE_NEEDS_CONFIGURATION, "service needs configuration");
|
||||||
REG_ERROR(ERROR_SERVICE_MOUNTPOINT_CONFLICT, "mountpoint already in use");
|
REG_ERROR(ERROR_SERVICE_MOUNTPOINT_CONFLICT, "service already exists");
|
||||||
|
REG_ERROR(ERROR_FOXX_MANIFEST_NOT_FOUND, "missing manifest file");
|
||||||
|
REG_ERROR(ERROR_FOXX_OPTIONS_MALFORMED, "failed to parse service options");
|
||||||
|
REG_ERROR(ERROR_FOXX_SOURCE_NOT_FOUND, "source path not found");
|
||||||
|
REG_ERROR(ERROR_FOXX_SOURCE_ERROR, "error resolving source");
|
||||||
REG_ERROR(ERROR_MODULE_NOT_FOUND, "cannot locate module");
|
REG_ERROR(ERROR_MODULE_NOT_FOUND, "cannot locate module");
|
||||||
REG_ERROR(ERROR_MODULE_FAILURE, "failed to invoke module");
|
REG_ERROR(ERROR_MODULE_FAILURE, "failed to invoke module");
|
||||||
REG_ERROR(ERROR_NO_SMART_COLLECTION, "collection is not smart");
|
REG_ERROR(ERROR_NO_SMART_COLLECTION, "collection is not smart");
|
||||||
|
|
|
@ -589,20 +589,28 @@
|
||||||
/// Will be raised when the client could not read data.
|
/// Will be raised when the client could not read data.
|
||||||
/// - 2100: @LIT{Request aborted}
|
/// - 2100: @LIT{Request aborted}
|
||||||
/// "Request was aborted."
|
/// "Request was aborted."
|
||||||
/// - 3000: @LIT{malformed manifest file}
|
/// - 3000: @LIT{failed to parse manifest file}
|
||||||
/// The manifest file is malformed. It is not in a valid JSON format.
|
/// The service manifest file is not well-formed JSON.
|
||||||
/// - 3001: @LIT{manifest file is invalid}
|
/// - 3001: @LIT{manifest file is invalid}
|
||||||
/// The manifest file of this service is invalid.
|
/// The service manifest contains invalid values.
|
||||||
/// - 3004: @LIT{invalid foxx options}
|
/// - 3004: @LIT{service options are invalid}
|
||||||
/// The options used to configure the foxx are invalid.
|
/// The service options contain invalid values.
|
||||||
/// - 3007: @LIT{mountpoint is invalid}
|
/// - 3007: @LIT{invalid mountpath}
|
||||||
/// mountpoint is invalid
|
/// The service mountpath contains invalid characters.
|
||||||
/// - 3009: @LIT{Service not found}
|
/// - 3009: @LIT{service not found}
|
||||||
/// No service found at this mountpoint
|
/// No service found at the given mountpath.
|
||||||
/// - 3010: @LIT{Service not configured}
|
/// - 3010: @LIT{service needs configuration}
|
||||||
/// The service has to be configured before it can be used
|
/// The service is missing configuration or dependencies.
|
||||||
/// - 3011: @LIT{mountpoint already in use}
|
/// - 3011: @LIT{service already exists}
|
||||||
/// A service has already been installed at this mountpoint
|
/// A service already exists at the given mountpath.
|
||||||
|
/// - 3012: @LIT{missing manifest file}
|
||||||
|
/// The service directory does not contain a manifest file.
|
||||||
|
/// - 3013: @LIT{failed to parse service options}
|
||||||
|
/// The service options are not well-formed JSON.
|
||||||
|
/// - 3014: @LIT{source path not found}
|
||||||
|
/// The source path does not match a file or directory.
|
||||||
|
/// - 3015: @LIT{error resolving source}
|
||||||
|
/// The source path could not be resolved.
|
||||||
/// - 3100: @LIT{cannot locate module}
|
/// - 3100: @LIT{cannot locate module}
|
||||||
/// The module path could not be resolved.
|
/// The module path could not be resolved.
|
||||||
/// - 3103: @LIT{failed to invoke module}
|
/// - 3103: @LIT{failed to invoke module}
|
||||||
|
@ -3140,9 +3148,9 @@ void TRI_InitializeErrorMessages ();
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3000: ERROR_MALFORMED_MANIFEST_FILE
|
/// @brief 3000: ERROR_MALFORMED_MANIFEST_FILE
|
||||||
///
|
///
|
||||||
/// malformed manifest file
|
/// failed to parse manifest file
|
||||||
///
|
///
|
||||||
/// The manifest file is malformed. It is not in a valid JSON format.
|
/// The service manifest file is not well-formed JSON.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_MALFORMED_MANIFEST_FILE (3000)
|
#define TRI_ERROR_MALFORMED_MANIFEST_FILE (3000)
|
||||||
|
@ -3152,7 +3160,7 @@ void TRI_InitializeErrorMessages ();
|
||||||
///
|
///
|
||||||
/// manifest file is invalid
|
/// manifest file is invalid
|
||||||
///
|
///
|
||||||
/// The manifest file of this service is invalid.
|
/// The service manifest contains invalid values.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_INVALID_SERVICE_MANIFEST (3001)
|
#define TRI_ERROR_INVALID_SERVICE_MANIFEST (3001)
|
||||||
|
@ -3160,9 +3168,9 @@ void TRI_InitializeErrorMessages ();
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3004: ERROR_INVALID_FOXX_OPTIONS
|
/// @brief 3004: ERROR_INVALID_FOXX_OPTIONS
|
||||||
///
|
///
|
||||||
/// invalid foxx options
|
/// service options are invalid
|
||||||
///
|
///
|
||||||
/// The options used to configure the foxx are invalid.
|
/// The service options contain invalid values.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_INVALID_FOXX_OPTIONS (3004)
|
#define TRI_ERROR_INVALID_FOXX_OPTIONS (3004)
|
||||||
|
@ -3170,9 +3178,9 @@ void TRI_InitializeErrorMessages ();
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3007: ERROR_INVALID_MOUNTPOINT
|
/// @brief 3007: ERROR_INVALID_MOUNTPOINT
|
||||||
///
|
///
|
||||||
/// mountpoint is invalid
|
/// invalid mountpath
|
||||||
///
|
///
|
||||||
/// mountpoint is invalid
|
/// The service mountpath contains invalid characters.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_INVALID_MOUNTPOINT (3007)
|
#define TRI_ERROR_INVALID_MOUNTPOINT (3007)
|
||||||
|
@ -3180,9 +3188,9 @@ void TRI_InitializeErrorMessages ();
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3009: ERROR_SERVICE_NOT_FOUND
|
/// @brief 3009: ERROR_SERVICE_NOT_FOUND
|
||||||
///
|
///
|
||||||
/// Service not found
|
/// service not found
|
||||||
///
|
///
|
||||||
/// No service found at this mountpoint
|
/// No service found at the given mountpath.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_SERVICE_NOT_FOUND (3009)
|
#define TRI_ERROR_SERVICE_NOT_FOUND (3009)
|
||||||
|
@ -3190,9 +3198,9 @@ void TRI_InitializeErrorMessages ();
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3010: ERROR_SERVICE_NEEDS_CONFIGURATION
|
/// @brief 3010: ERROR_SERVICE_NEEDS_CONFIGURATION
|
||||||
///
|
///
|
||||||
/// Service not configured
|
/// service needs configuration
|
||||||
///
|
///
|
||||||
/// The service has to be configured before it can be used
|
/// The service is missing configuration or dependencies.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_SERVICE_NEEDS_CONFIGURATION (3010)
|
#define TRI_ERROR_SERVICE_NEEDS_CONFIGURATION (3010)
|
||||||
|
@ -3200,13 +3208,53 @@ void TRI_InitializeErrorMessages ();
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3011: ERROR_SERVICE_MOUNTPOINT_CONFLICT
|
/// @brief 3011: ERROR_SERVICE_MOUNTPOINT_CONFLICT
|
||||||
///
|
///
|
||||||
/// mountpoint already in use
|
/// service already exists
|
||||||
///
|
///
|
||||||
/// A service has already been installed at this mountpoint
|
/// A service already exists at the given mountpath.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#define TRI_ERROR_SERVICE_MOUNTPOINT_CONFLICT (3011)
|
#define TRI_ERROR_SERVICE_MOUNTPOINT_CONFLICT (3011)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief 3012: ERROR_FOXX_MANIFEST_NOT_FOUND
|
||||||
|
///
|
||||||
|
/// missing manifest file
|
||||||
|
///
|
||||||
|
/// The service directory does not contain a manifest file.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define TRI_ERROR_FOXX_MANIFEST_NOT_FOUND (3012)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief 3013: ERROR_FOXX_OPTIONS_MALFORMED
|
||||||
|
///
|
||||||
|
/// failed to parse service options
|
||||||
|
///
|
||||||
|
/// The service options are not well-formed JSON.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define TRI_ERROR_FOXX_OPTIONS_MALFORMED (3013)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief 3014: ERROR_FOXX_SOURCE_NOT_FOUND
|
||||||
|
///
|
||||||
|
/// source path not found
|
||||||
|
///
|
||||||
|
/// The source path does not match a file or directory.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define TRI_ERROR_FOXX_SOURCE_NOT_FOUND (3014)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
/// @brief 3015: ERROR_FOXX_SOURCE_ERROR
|
||||||
|
///
|
||||||
|
/// error resolving source
|
||||||
|
///
|
||||||
|
/// The source path could not be resolved.
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#define TRI_ERROR_FOXX_SOURCE_ERROR (3015)
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
/// @brief 3100: ERROR_MODULE_NOT_FOUND
|
/// @brief 3100: ERROR_MODULE_NOT_FOUND
|
||||||
///
|
///
|
||||||
|
|
Loading…
Reference in New Issue