Skip to content

Commit

Permalink
Add collection delete (#1501)
Browse files Browse the repository at this point in the history
## What does this PR do ?

Add collection delete

https://deploy-preview-1501--doc-kuzzle.netlify.com/api/controllers/collection/delete/

### Other changes

 - do not list malformated esIndex created apart from Kuzzle (eg: `&nyc-open-data.`)
  • Loading branch information
Aschen committed Nov 4, 2019
1 parent 031d2d8 commit fbd7e0c
Show file tree
Hide file tree
Showing 15 changed files with 179 additions and 28 deletions.
2 changes: 1 addition & 1 deletion bin/start-kuzzle-server
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function startKuzzle (options = {}) {

return kuzzle.start(kuzzleParams)
.then(() => {
cout.ok('[✔] Kuzzle server ready');
cout.ok(`[✔] Kuzzle server ${require('../package.json').version} ready`);

return kuzzle.adminExists();
})
Expand Down
64 changes: 64 additions & 0 deletions doc/2/api/controllers/collection/delete/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
code: true
type: page
title: delete
---

# delete

Deletes a [collection](/core/2/guides/essentials/store-access-data).

---

## Query Syntax

### HTTP

```http
URL: http://kuzzle:7512/<index>/<collection>
Method: DELETE
```

### Other protocols

```js
{
"index": "<index>",
"collection": "<collection>",
"controller": "collection",
"action": "delete"
}
```

---

## Arguments

- `collection`: collection name
- `index`: index name

---

## Response

Returns a confirmation that the collection is deleted:

```js
{
"status": 200,
"error": null,
"index": "<index>",
"collection": "<collection>",
"controller": "collection",
"action": "delete",
"requestId": "<unique request identifier>",
"result": null
}
```

---

## Possible errors

- [Common errors](/core/2/api/essentials/errors/handling#common-errors)
- [PreconditionError](/core/2/api/essentials/errors/handling#preconditionerror)
1 change: 1 addition & 0 deletions doc/2/guides/upgrade-kuzzle/changes/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ Indexes not following this naming policy cannot be accessed by Kuzzle's API.
### New API methods

- `collection:refresh`: refreshes a collection
- `collection:delete`: deletes a collection

### Removed API methods

Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ services:
- DEBUG_COLORS=${DEBUG_COLORS:-on}
- KUZZLE_VAULT_KEY=${KUZZLE_VAULT_KEY}
- NODE_10_VERSION=10.16.0
- WITHOUT_KUZZLE=${WITHOUT_KUZZLE}

redis:
image: redis:${REDIS_VERSION:-5}
Expand Down
4 changes: 4 additions & 0 deletions docker-compose/scripts/run-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

set -e

if [ ! -z "$WITHOUT_KUZZLE" ]; then
exit 0
fi

elastic_host=${kuzzle_services__storageEngine__client__node:-http://elasticsearch:9200}

if [ ! -z "$TRAVIS" ] || [ ! -z "$REBUILD" ]; then
Expand Down
12 changes: 11 additions & 1 deletion features-sdk/CollectionController.feature
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
Feature: Collection Controller

# collection:delete ==========================================================

Scenario: Delete a collection
Given an index "nyc-open-data"
And a collection "nyc-open-data":"green-taxi"
When I successfully call the route "collection":"delete" with args:
| index | "nyc-open-data" |
| collection | "green-taxi" |
Then I should not see the collection "nyc-open-data":"green-taxi"

# collection:create ==========================================================

Scenario: Create a new collection with mappings
Given an index "nyc-open-data"
When I call the route "collection":"create" with args:
When I successfully call the route "collection":"create" with args:
| index | "nyc-open-data" |
| collection | "green-taxi" |
| body | { "dynamic": "strict", "properties": { "name": { "type": "keyword" } } } |
Expand Down
19 changes: 17 additions & 2 deletions lib/api/controllers/collectionController.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class CollectionController extends BaseController {
'updateMapping',
'updateSpecifications',
'validateSpecifications',
'refresh'
'refresh',
'delete'
]);

this.defaultScrollTTL = this.kuzzle.storageEngine.config.defaults.scrollTTL;
Expand Down Expand Up @@ -360,6 +361,21 @@ class CollectionController extends BaseController {
.then(() => null);
}

/**
* Deletes a collection
*
* @param {String} index
* @param {String} collection
*
* @returns {Promise}
*/
delete (request) {
const { index, collection } = this.getIndexAndCollection(request);

return this.publicStorage.deleteCollection(index, collection)
.then(() => null);
}


/**
* Uses from and size to paginate response results
Expand Down Expand Up @@ -395,4 +411,3 @@ class CollectionController extends BaseController {
}

module.exports = CollectionController;

3 changes: 2 additions & 1 deletion lib/api/core/storage/clientAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ class ClientAdapter {

// Methods that needs to assert index existence
this._assertIndexMethods = [
'listCollections'
'listCollections',
'deleteCollection'
];

// Methods directly bound to the storageClient
Expand Down
3 changes: 2 additions & 1 deletion lib/api/core/storage/indexStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ class IndexStorage {
'refreshCollection',
'deleteIndex',
'getMapping',
'updateMapping'
'updateMapping',
'deleteCollection'
];

// we need to declare these method to keep backward compat with Repository API
Expand Down
2 changes: 2 additions & 0 deletions lib/config/httpRoutes.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,8 @@ module.exports = [
{verb: 'delete', url: '/:index', controller: 'index', action: 'delete'},
{verb: 'delete', url: '/_mdelete', controller: 'index', action: 'mDelete'},

{verb: 'delete', url: '/:index/:collection', controller: 'collection', action: 'delete'},

{verb: 'delete', url: '/profiles/:_id', controller: 'security', action: 'deleteProfile'},
{verb: 'delete', url: '/roles/:_id', controller: 'security', action: 'deleteRole'},
{verb: 'delete', url: '/users/:_id', controller: 'security', action: 'deleteUser'},
Expand Down
45 changes: 29 additions & 16 deletions lib/services/elasticsearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -611,9 +611,7 @@ class ElasticSearch extends Service {

debug('Delete document: %o', esRequest);
return this._client.delete(esRequest)
.then(() => {
// return nothing
})
.then(() => null)
.catch(error => this._esWrapper.reject(error));
}

Expand Down Expand Up @@ -708,9 +706,7 @@ class ElasticSearch extends Service {

return this._client.indices.create(esRequest);
})
.then(() => {
// return nothing
})
.then(() => null)
.catch(error => this._esWrapper.reject(error));
}

Expand Down Expand Up @@ -752,9 +748,7 @@ class ElasticSearch extends Service {
};

return this._client.indices.create(esRequest)
.then(() => {
// return nothing
})
.then(() => null)
.catch(error => this._esWrapper.reject(error));
});
}
Expand Down Expand Up @@ -853,9 +847,7 @@ class ElasticSearch extends Service {
return this._client.indices.delete(esRequest);
})
.then(() => this._client.indices.create({ ...esRequest, body: { mappings } }))
.then(() => {
// return nothing
})
.then(() => null)
.catch(error => this._esWrapper.reject(error));
}

Expand Down Expand Up @@ -1057,6 +1049,24 @@ class ElasticSearch extends Service {
.catch(error => this._esWrapper.reject(error));
}

/**
* Deletes a collection
*
* @param {String} index - Index name
* @param {String} collection - Collection name
*
* @returns {Promise}
*/
deleteCollection (index, collection) {
const esRequest = {
index: this._getESIndex(index, collection)
};

return this._client.indices.delete(esRequest)
.then(() => null)
.catch(error => this._esWrapper.reject(error));
}

/**
* Deletes multiple indexes
*
Expand Down Expand Up @@ -1107,9 +1117,7 @@ class ElasticSearch extends Service {
*/
deleteIndex (index) {
return this.deleteIndexes([index])
.then(() => {
// return nothing
});
.then(() => null);
}

/**
Expand Down Expand Up @@ -1842,7 +1850,12 @@ class ElasticSearch extends Service {
const indexes = new Set();

for (const esIndex of esIndexes) {
if (esIndex[0] === this._indexPrefix) {
const separatorIndex = esIndex.indexOf(NAME_SEPARATOR);

if ( esIndex[0] === this._indexPrefix
&& separatorIndex !== -1
&& separatorIndex !== esIndex.length -1
) {
indexes.add(this._extractIndex(esIndex));
}
}
Expand Down
11 changes: 11 additions & 0 deletions test/api/controllers/collectionController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -508,4 +508,15 @@ describe('Test: collection controller', () => {
});
});
});

describe('#delete', () => {
it('should call deleteCollection', async () => {
const response = await collectionController.delete(request);

should(collectionController.publicStorage.deleteCollection)
.be.calledWith(index, collection);

should(response).be.null();
});
});
});
1 change: 1 addition & 0 deletions test/mocks/clientAdapter.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class ClientAdapterMock extends ClientAdapter {
this.mUpdate = sinon.stub().resolves();
this.mReplace = sinon.stub().resolves();
this.mDelete = sinon.stub().resolves();
this.deleteCollection = sinon.stub().resolves();
}
}

Expand Down
1 change: 1 addition & 0 deletions test/mocks/elasticsearch.mock.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class ElasticsearchMock extends Elasticsearch {
this.mUpdate = sinon.stub().resolves();
this.mReplace = sinon.stub().resolves();
this.mDelete = sinon.stub().resolves();
this.deleteCollection = sinon.stub().resolves();
}
}

Expand Down
Loading

0 comments on commit fbd7e0c

Please sign in to comment.