1
0
Fork 0

Fix Foxx API (#4614)

This commit is contained in:
Mark 2018-02-20 10:22:27 +01:00 committed by Jan
parent 1c80774091
commit cd97787adf
5 changed files with 75 additions and 9 deletions

View File

@ -1,7 +1,12 @@
devel
-----
* renamed startup option `--replication.automatic-failover` to
* fixed Foxx API:
* PUT /_api/foxx/service: Respect force flag
* PATCH /_api/foxx/service: Check whether a service under given mount exists
* renamed startup option `--replication.automatic-failover` to
`--replication.active-failover`
using the old option name will still work in ArangoDB 3.4, but the old option
will be removed afterwards
@ -12,7 +17,7 @@ devel
inaccurate estimates. The issue is solved now, but there can be up to a second
or so delay before updates are reflected in the estimates.
* support `returnOld` and `returnNew` attributes for in the following HTTP REST
* support `returnOld` and `returnNew` attributes for in the following HTTP REST
APIs:
* /_api/gharial/<graph>/vertex/<collection>
@ -21,7 +26,7 @@ devel
The exception from this is that the HTTP DELETE verb for these APIs does not
support `returnOld` because that would make the existing API incompatible
* fixed issue #4160: Run arangod with "--database.auto-upgrade" option always crash
* fixed issue #4160: Run arangod with "--database.auto-upgrade" option always crash
silently without error log
* fix issue #4457: create /var/tmp/arangod with correct user in supervisor mode

View File

@ -53,6 +53,9 @@ Set to `false` to not run the new service's setup script.
@RESTQUERYPARAM{legacy,boolean,optional}
Set to `true` to install the new service in 2.8 legacy compatibility mode.
@RESTQUERYPARAM{force,boolean,optional}
Set to `true` to force service install even if no service is installed under given mount.
@RESTRETURNCODES
@RESTRETURNCODE{200}

View File

@ -199,6 +199,7 @@ serviceRouter.put(prepareServiceRequestBody, (req, res) => {
.queryParam('teardown', schemas.flag.default(true))
.queryParam('setup', schemas.flag.default(true))
.queryParam('legacy', schemas.flag.default(false))
.queryParam('force', schemas.flag.default(false))
.response(200, schemas.fullInfo);
serviceRouter.delete((req, res) => {

View File

@ -1288,8 +1288,8 @@ describe('Foxx service', () => {
const routes = [
['GET', '/_api/foxx/service'],
['PATCH', '/_api/foxx/service'],
['PUT', '/_api/foxx/service'],
['PATCH', '/_api/foxx/service', { source: servicePath }],
['PUT', '/_api/foxx/service', { source: servicePath }],
['DELETE', '/_api/foxx/service'],
['GET', '/_api/foxx/configuration'],
['PATCH', '/_api/foxx/configuration'],
@ -1306,20 +1306,22 @@ describe('Foxx service', () => {
['GET', '/_api/foxx/readme'],
['GET', '/_api/foxx/swagger']
];
for (const [method, url] of routes) {
for (const [method, url, body] of routes) {
it(`should return 400 when mount is omitted for ${method} ${url}`, () => {
const resp = request({
method,
url,
body,
json: true
});
expect(resp.status).to.equal(400);
});
it(`should return 400 when mount is invalid for ${method} ${url}`, () => {
it(`should return 400 when mount is unknown for ${method} ${url}`, () => {
const resp = request({
method,
url,
qs: {mount: '/dev/null'},
body,
json: true
});
expect(resp.status).to.equal(400);
@ -1337,4 +1339,36 @@ describe('Foxx service', () => {
expect(resp.json).to.have.property('failures');
expect(resp.json).to.have.property('passes');
});
it('replace on invalid mount should not be installed', () => {
const replaceResp = request.put('/_api/foxx/service', {
qs: {
mount
},
body: {
source: servicePath
},
json: true
});
expect(replaceResp.status).to.equal(400);
const resp = request.get(mount);
expect(resp.status).to.equal(404);
});
it('replace on invalid mount should be installed when forced', () => {
const replaceResp = request.put('/_api/foxx/service', {
qs: {
mount,
force: true
},
body: {
source: servicePath
},
json: true
});
expect(replaceResp.status).to.equal(200);
const resp = request.get(mount);
expect(resp.status).to.equal(200);
expect(resp.json).to.eql({hello: 'world'});
});
});

View File

@ -860,8 +860,21 @@ function uninstall (mount, options = {}) {
}
function replace (serviceInfo, mount, options = {}) {
utils.validateMount(mount);
ensureFoxxInitialized();
if (!options.force) {
const serviceDefinition = utils.getServiceDefinition(mount);
if (!serviceDefinition) {
throw new ArangoError({
errorNum: errors.ERROR_SERVICE_NOT_FOUND.code,
errorMessage: dd`
${errors.ERROR_SERVICE_NOT_FOUND.message}
Mount path: "${mount}".
`
});
}
} else {
utils.validateMount(mount);
}
const tempPaths = _prepareService(serviceInfo, options);
FoxxService.validatedManifest({
mount,
@ -877,7 +890,17 @@ function replace (serviceInfo, mount, options = {}) {
function upgrade (serviceInfo, mount, options = {}) {
ensureFoxxInitialized();
const serviceOptions = utils.getServiceDefinition(mount).options;
const serviceDefinition = utils.getServiceDefinition(mount);
if (!serviceDefinition) {
throw new ArangoError({
errorNum: errors.ERROR_SERVICE_NOT_FOUND.code,
errorMessage: dd`
${errors.ERROR_SERVICE_NOT_FOUND.message}
Mount path: "${mount}".
`
});
}
const serviceOptions = serviceDefinition.options;
Object.assign(serviceOptions.configuration, options.configuration);
Object.assign(serviceOptions.dependencies, options.dependencies);
serviceOptions.development = options.development;