METRON-1771 Update REST endpoints to support eventually consistent UI updates (merrimanr) closes apache/metron#1190
Project: http://git-wip-us.apache.org/repos/asf/metron/repo Commit: http://git-wip-us.apache.org/repos/asf/metron/commit/de533063 Tree: http://git-wip-us.apache.org/repos/asf/metron/tree/de533063 Diff: http://git-wip-us.apache.org/repos/asf/metron/diff/de533063 Branch: refs/heads/master Commit: de533063c26c8a2462dbfff33228a949c4a96c97 Parents: 7e222fa Author: merrimanr <[email protected]> Authored: Thu Oct 4 17:16:18 2018 -0500 Committer: rmerriman <[email protected]> Committed: Thu Oct 4 17:16:18 2018 -0500 ---------------------------------------------------------------------- metron-interface/metron-rest/README.md | 16 ++ .../rest/controller/MetaAlertController.java | 18 +- .../rest/controller/UpdateController.java | 31 ++- .../metron/rest/service/MetaAlertService.java | 12 +- .../metron/rest/service/UpdateService.java | 9 +- .../rest/service/impl/MetaAlertServiceImpl.java | 18 +- .../rest/service/impl/UpdateServiceImpl.java | 18 +- .../MetaAlertControllerIntegrationTest.java | 152 +++++++------- .../elasticsearch/dao/ElasticsearchDao.java | 32 +-- .../dao/ElasticsearchMetaAlertDao.java | 37 ++-- .../dao/ElasticsearchMetaAlertUpdateDao.java | 55 ++--- .../dao/ElasticsearchUpdateDao.java | 42 ++-- .../dao/ElasticsearchMetaAlertDaoTest.java | 27 ++- .../dao/ElasticsearchUpdateDaoTest.java | 52 +++++ .../apache/metron/indexing/dao/HBaseDao.java | 31 +-- .../metron/indexing/dao/MultiIndexDao.java | 138 ++++++++----- .../dao/metaalert/MetaAlertCreateResponse.java | 40 ---- .../dao/metaalert/MetaAlertUpdateDao.java | 20 +- .../AbstractLuceneMetaAlertUpdateDao.java | 81 +++++++- .../metron/indexing/dao/update/UpdateDao.java | 25 ++- .../InMemoryMetaAlertRetrieveLatestDao.java | 49 +++++ .../metron/indexing/dao/HBaseDaoTest.java | 41 ++++ .../apache/metron/indexing/dao/InMemoryDao.java | 18 +- .../indexing/dao/InMemoryMetaAlertDao.java | 199 +++++-------------- .../dao/InMemoryMetaAlertUpdateDao.java | 91 +++++++++ .../metron/indexing/dao/MultiIndexDaoTest.java | 96 +++++++++ .../metron/indexing/dao/UpdateDaoTest.java | 74 +++++++ .../indexing/dao/UpdateIntegrationTest.java | 138 +++++++------ .../dao/metaalert/MetaAlertIntegrationTest.java | 119 ++++++++--- .../AbstractLuceneMetaAlertUpdateDaoTest.java | 56 ++++-- .../integration/HBaseDaoIntegrationTest.java | 7 +- .../org/apache/metron/solr/dao/SolrDao.java | 28 +-- .../metron/solr/dao/SolrMetaAlertDao.java | 49 +++-- .../metron/solr/dao/SolrMetaAlertUpdateDao.java | 38 ++-- .../apache/metron/solr/dao/SolrUpdateDao.java | 36 ++-- .../metron/solr/dao/SolrMetaAlertDaoTest.java | 21 +- .../metron/solr/dao/SolrUpdateDaoTest.java | 19 +- 37 files changed, 1206 insertions(+), 727 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/README.md ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/README.md b/metron-interface/metron-rest/README.md index 2c216d1..2ce9522 100644 --- a/metron-interface/metron-rest/README.md +++ b/metron-interface/metron-rest/README.md @@ -336,6 +336,8 @@ Request and Response objects are JSON formatted. The JSON schemas are available | [ `GET /api/v1/storm/supervisors`](#get-apiv1stormsupervisors)| | [ `PATCH /api/v1/update/patch`](#patch-apiv1updatepatch)| | [ `PUT /api/v1/update/replace`](#put-apiv1updatereplace)| +| [ `POST /api/v1/update/add/comment`](#put-apiv1updateaddcomment)| +| [ `POST /api/v1/update/remove/comment`](#put-apiv1updateremovecomment)| | [ `GET /api/v1/user`](#get-apiv1user)| ### `POST /api/v1/alerts/ui/escalate` @@ -963,6 +965,20 @@ Request and Response objects are JSON formatted. The JSON schemas are available ``` * Returns: * 200 - Current user + +### `POST /api/v1/update/add/comment` + * Description: Add a comment to an alert + * Input: + * request - Comment add request + * Returns: + * 200 - Returns the complete alert document with comments added. + +### `POST /api/v1/update/remove/comment` + * Description: Remove a comment from an alert + * Input: + * request - Comment remove request + * Returns: + * 200 - Returns the complete alert document with comments removed. ### `GET /api/v1/user` * Description: Retrieves the current user http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/MetaAlertController.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/MetaAlertController.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/MetaAlertController.java index d42403a..69b1779 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/MetaAlertController.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/MetaAlertController.java @@ -24,8 +24,8 @@ import io.swagger.annotations.ApiResponse; import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus; import org.apache.metron.indexing.dao.metaalert.MetaAlertAddRemoveRequest; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; import org.apache.metron.indexing.dao.search.SearchResponse; +import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.rest.RestException; import org.apache.metron.rest.service.MetaAlertService; import org.springframework.beans.factory.annotation.Autowired; @@ -57,9 +57,9 @@ public class MetaAlertController { @ApiOperation(value = "Creates a new meta alert from a list of existing alerts. " + "The meta alert status will initially be set to 'ACTIVE' and summary statistics " + "will be computed from the list of alerts. A list of groups included in the request are also added to the meta alert.") - @ApiResponse(message = "The GUID of the new meta alert", code = 200) + @ApiResponse(message = "Returns the complete document of the created metaalert.", code = 200) @RequestMapping(value = "/create", method = RequestMethod.POST) - ResponseEntity<MetaAlertCreateResponse> create( + ResponseEntity<Document> create( @ApiParam(name = "createRequest", value = "Meta alert create request which includes a list of alert " + "get requests and a list of custom groups used to annotate a meta alert", required = true) @RequestBody final MetaAlertCreateRequest createRequest @@ -68,9 +68,9 @@ public class MetaAlertController { } @ApiOperation(value = "Adds an alert to an existing meta alert. An alert will not be added if it is already contained in a meta alert.") - @ApiResponse(message = "Returns 'true' if the alert was added and 'false' if the meta alert did not change.", code = 200) + @ApiResponse(message = "Returns the complete metaalert document with the alerts added.", code = 200) @RequestMapping(value = "/add/alert", method = RequestMethod.POST) - ResponseEntity<Boolean> addAlertsToMetaAlert( + ResponseEntity<Document> addAlertsToMetaAlert( @ApiParam(name = "metaAlertAddRemoveRequest", value = "Meta alert add request which includes a meta alert GUID and list of alert get requests", required = true) @RequestBody final MetaAlertAddRemoveRequest metaAlertAddRemoveRequest ) throws RestException { @@ -78,9 +78,9 @@ public class MetaAlertController { } @ApiOperation(value = "Removes an alert from an existing meta alert. If the alert to be removed is not in a meta alert, 'false' will be returned.") - @ApiResponse(message = "Returns 'true' if the alert was removed and 'false' if the meta alert did not change.", code = 200) + @ApiResponse(message = "Returns the complete metaalert document with the alerts removed.", code = 200) @RequestMapping(value = "/remove/alert", method = RequestMethod.POST) - ResponseEntity<Boolean> removeAlertsFromMetaAlert( + ResponseEntity<Document> removeAlertsFromMetaAlert( @ApiParam(name = "metaAlertAddRemoveRequest", value = "Meta alert remove request which includes a meta alert GUID and list of alert get requests", required = true) @RequestBody final MetaAlertAddRemoveRequest metaAlertAddRemoveRequest ) throws RestException { @@ -88,9 +88,9 @@ public class MetaAlertController { } @ApiOperation(value = "Updates the status of a meta alert to either 'ACTIVE' or 'INACTIVE'.") - @ApiResponse(message = "Returns 'true' if the status changed and 'false' if it did not.", code = 200) + @ApiResponse(message = "Returns the complete metaalert document with the updated status.", code = 200) @RequestMapping(value = "/update/status/{guid}/{status}", method = RequestMethod.POST) - ResponseEntity<Boolean> updateMetaAlertStatus( + ResponseEntity<Document> updateMetaAlertStatus( final @ApiParam(name = "guid", value = "Meta alert GUID", required = true) @PathVariable String guid, final @ApiParam(name = "status", value = "Meta alert status with a value of either 'ACTIVE' or 'INACTIVE'", required = true) http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/UpdateController.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/UpdateController.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/UpdateController.java index 609442b..5550358 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/UpdateController.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/controller/UpdateController.java @@ -21,6 +21,7 @@ import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import io.swagger.annotations.ApiResponse; import org.apache.metron.indexing.dao.update.CommentAddRemoveRequest; +import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.indexing.dao.update.OriginalNotFoundException; import org.apache.metron.indexing.dao.update.PatchRequest; import org.apache.metron.indexing.dao.update.ReplaceRequest; @@ -42,52 +43,48 @@ public class UpdateController { private UpdateService service; @ApiOperation(value = "Update a document with a patch") - @ApiResponse(message = "Nothing", code = 200) + @ApiResponse(message = "Returns the complete patched document.", code = 200) @RequestMapping(value = "/patch", method = RequestMethod.PATCH) - ResponseEntity<Void> patch( + ResponseEntity<Document> patch( final @ApiParam(name = "request", value = "Patch request", required = true) @RequestBody PatchRequest request ) throws RestException { try { - service.patch(request); + return new ResponseEntity<>(service.patch(request), HttpStatus.OK); } catch (OriginalNotFoundException e) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - return new ResponseEntity<>(HttpStatus.OK); } @ApiOperation(value = "Replace a document with a full replacement") - @ApiResponse(message = "Nothing", code = 200) + @ApiResponse(message = "Returns the complete replaced document.", code = 200) @RequestMapping(value = "/replace", method = RequestMethod.POST) - ResponseEntity<Void> replace( + ResponseEntity<Document> replace( final @ApiParam(name = "request", value = "Replacement request", required = true) @RequestBody ReplaceRequest request ) throws RestException { - service.replace(request); - return new ResponseEntity<>(HttpStatus.OK); + return new ResponseEntity<>(service.replace(request), HttpStatus.OK); } @ApiOperation(value = "Add a comment to an alert") - @ApiResponse(message = "Nothing", code = 200) + @ApiResponse(message = "Returns the complete alert document with comments added.", code = 200) @RequestMapping(value = "/add/comment", method = RequestMethod.POST) - ResponseEntity<Void> addCommentToAlert( + ResponseEntity<Document> addCommentToAlert( @RequestBody @ApiParam(name = "request", value = "Comment add request", required = true) final CommentAddRemoveRequest request ) throws RestException { - service.addComment(request); - return new ResponseEntity<>(HttpStatus.OK); + return new ResponseEntity<>(service.addComment(request), HttpStatus.OK); } - @ApiOperation(value = "Remove a comment to an alert") - @ApiResponse(message = "Nothing", code = 200) + @ApiOperation(value = "Remove a comment from an alert") + @ApiResponse(message = "Returns the complete alert document with comments removed.", code = 200) @RequestMapping(value = "/remove/comment", method = RequestMethod.POST) - ResponseEntity<Void> removeCommentFromAlert( + ResponseEntity<Document> removeCommentFromAlert( @RequestBody @ApiParam(name = "request", value = "Comment remove request", required = true) final CommentAddRemoveRequest request ) throws RestException { - service.removeComment(request); - return new ResponseEntity<>(HttpStatus.OK); + return new ResponseEntity<>(service.removeComment(request), HttpStatus.OK); } } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/MetaAlertService.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/MetaAlertService.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/MetaAlertService.java index e8abaf3..4ebebb6 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/MetaAlertService.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/MetaAlertService.java @@ -18,24 +18,22 @@ package org.apache.metron.rest.service; -import java.io.IOException; -import java.util.Collection; import org.apache.metron.indexing.dao.metaalert.MetaAlertAddRemoveRequest; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus; import org.apache.metron.indexing.dao.search.SearchResponse; +import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.rest.RestException; public interface MetaAlertService { - MetaAlertCreateResponse create(MetaAlertCreateRequest createRequest) throws RestException; + Document create(MetaAlertCreateRequest createRequest) throws RestException; SearchResponse getAllMetaAlertsForAlert(String guid) throws RestException; - boolean addAlertsToMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException; + Document addAlertsToMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException; - boolean removeAlertsFromMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException; + Document removeAlertsFromMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException; - boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws RestException; + Document updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws RestException; } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/UpdateService.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/UpdateService.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/UpdateService.java index bd59f39..19b3485 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/UpdateService.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/UpdateService.java @@ -18,6 +18,7 @@ package org.apache.metron.rest.service; import org.apache.metron.indexing.dao.update.CommentAddRemoveRequest; +import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.indexing.dao.update.OriginalNotFoundException; import org.apache.metron.indexing.dao.update.PatchRequest; import org.apache.metron.indexing.dao.update.ReplaceRequest; @@ -25,8 +26,8 @@ import org.apache.metron.rest.RestException; public interface UpdateService { - void patch(PatchRequest request) throws RestException, OriginalNotFoundException; - void replace(ReplaceRequest request) throws RestException; - void addComment(CommentAddRemoveRequest request) throws RestException; - void removeComment(CommentAddRemoveRequest request) throws RestException; + Document patch(PatchRequest request) throws RestException, OriginalNotFoundException; + Document replace(ReplaceRequest request) throws RestException; + Document addComment(CommentAddRemoveRequest request) throws RestException; + Document removeComment(CommentAddRemoveRequest request) throws RestException; } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/MetaAlertServiceImpl.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/MetaAlertServiceImpl.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/MetaAlertServiceImpl.java index 3f9b3e4..bd8419f 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/MetaAlertServiceImpl.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/MetaAlertServiceImpl.java @@ -23,11 +23,11 @@ import org.apache.metron.indexing.dao.IndexDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertAddRemoveRequest; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus; import org.apache.metron.indexing.dao.search.InvalidCreateException; import org.apache.metron.indexing.dao.search.InvalidSearchException; import org.apache.metron.indexing.dao.search.SearchResponse; +import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.rest.RestException; import org.apache.metron.rest.service.MetaAlertService; import org.springframework.beans.factory.annotation.Autowired; @@ -47,7 +47,7 @@ public class MetaAlertServiceImpl implements MetaAlertService { } @Override - public MetaAlertCreateResponse create(MetaAlertCreateRequest createRequest) throws RestException { + public Document create(MetaAlertCreateRequest createRequest) throws RestException { try { return dao.createMetaAlert(createRequest); } catch (InvalidCreateException | IOException e) { @@ -65,25 +65,25 @@ public class MetaAlertServiceImpl implements MetaAlertService { } @Override - public boolean addAlertsToMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException { + public Document addAlertsToMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException { try { return dao.addAlertsToMetaAlert(metaAlertAddRemoveRequest.getMetaAlertGuid(), metaAlertAddRemoveRequest.getAlerts()); - } catch (IOException ioe) { - throw new RestException(ioe.getMessage(), ioe); + } catch (IOException | IllegalStateException e) { + throw new RestException(e.getMessage(), e); } } @Override - public boolean removeAlertsFromMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException { + public Document removeAlertsFromMetaAlert(MetaAlertAddRemoveRequest metaAlertAddRemoveRequest) throws RestException { try { return dao.removeAlertsFromMetaAlert(metaAlertAddRemoveRequest.getMetaAlertGuid(), metaAlertAddRemoveRequest.getAlerts()); - } catch (IOException ioe) { - throw new RestException(ioe.getMessage(), ioe); + } catch (IOException | IllegalStateException e) { + throw new RestException(e.getMessage(), e); } } @Override - public boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) + public Document updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws RestException { try { return dao.updateMetaAlertStatus(metaAlertGuid, status); http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/UpdateServiceImpl.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/UpdateServiceImpl.java b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/UpdateServiceImpl.java index 49490fd..63dd4c0 100644 --- a/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/UpdateServiceImpl.java +++ b/metron-interface/metron-rest/src/main/java/org/apache/metron/rest/service/impl/UpdateServiceImpl.java @@ -19,6 +19,7 @@ package org.apache.metron.rest.service.impl; import org.apache.metron.indexing.dao.IndexDao; import org.apache.metron.indexing.dao.update.CommentAddRemoveRequest; +import org.apache.metron.indexing.dao.update.Document; import org.apache.metron.indexing.dao.update.OriginalNotFoundException; import org.apache.metron.indexing.dao.update.PatchRequest; import org.apache.metron.indexing.dao.update.ReplaceRequest; @@ -43,37 +44,36 @@ public class UpdateServiceImpl implements UpdateService { @Override - public void patch(PatchRequest request) throws RestException, OriginalNotFoundException { + public Document patch(PatchRequest request) throws RestException, OriginalNotFoundException { try { - dao.patch(dao, request, Optional.of(System.currentTimeMillis())); + return dao.patch(dao, request, Optional.of(System.currentTimeMillis())); } catch (Exception e) { - throw new RestException(e.getMessage(), e); } } @Override - public void replace(ReplaceRequest request) throws RestException { + public Document replace(ReplaceRequest request) throws RestException { try { - dao.replace(request, Optional.of(System.currentTimeMillis())); + return dao.replace(request, Optional.of(System.currentTimeMillis())); } catch (Exception e) { throw new RestException(e.getMessage(), e); } } @Override - public void addComment(CommentAddRemoveRequest request) throws RestException { + public Document addComment(CommentAddRemoveRequest request) throws RestException { try { - dao.addCommentToAlert(request); + return dao.addCommentToAlert(request); } catch (Exception e) { throw new RestException(e.getMessage(), e); } } @Override - public void removeComment(CommentAddRemoveRequest request) throws RestException { + public Document removeComment(CommentAddRemoveRequest request) throws RestException { try { - dao.removeCommentFromAlert(request); + return dao.removeCommentFromAlert(request); } catch (Exception e) { throw new RestException(e.getMessage(), e); } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/MetaAlertControllerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/MetaAlertControllerIntegrationTest.java b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/MetaAlertControllerIntegrationTest.java index b216990..8e3abe5 100644 --- a/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/MetaAlertControllerIntegrationTest.java +++ b/metron-interface/metron-rest/src/test/java/org/apache/metron/rest/controller/MetaAlertControllerIntegrationTest.java @@ -19,6 +19,10 @@ package org.apache.metron.rest.controller; import static org.apache.metron.rest.MetronRestConstants.TEST_PROFILE; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.notNullValue; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf; import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic; import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; @@ -29,15 +33,13 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. import com.google.common.collect.ImmutableMap; import java.util.ArrayList; -import java.util.Arrays; import org.adrianwalker.multilinestring.Multiline; import org.apache.curator.framework.CuratorFramework; import org.apache.metron.common.utils.JSONUtils; import org.apache.metron.indexing.dao.InMemoryMetaAlertDao; import org.apache.metron.indexing.dao.SearchIntegrationTest; import org.apache.metron.indexing.dao.metaalert.MetaAlertAddRemoveRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; +import org.apache.metron.indexing.dao.metaalert.MetaAlertConstants; import org.apache.metron.indexing.dao.search.GetRequest; import org.apache.metron.rest.service.MetaAlertService; import org.junit.After; @@ -96,8 +98,8 @@ public class MetaAlertControllerIntegrationTest extends DaoControllerTest { /** * [ - *{"guid":"meta_1","metron_alert":[{"guid":"bro_1"}],"average":"5.0","min":"5.0","median":"5.0","max":"5.0","count":"1.0","sum":"5.0"}, - *{"guid":"meta_2","metron_alert":[{"guid":"bro_1"},{"guid":"bro_2"},{"guid":"snort_1"}],"average":"5.0","min":"0.0","median":"5.0","max":"10.0","count":"3.0","sum":"15.0"} + *{"guid":"meta_1","metron_alert":[{"guid":"bro_1", "source.type":"bro"}],"average":"5.0","min":"5.0","median":"5.0","max":"5.0","count":"1.0","sum":"5.0", "status":"active"}, + *{"guid":"meta_2","metron_alert":[{"guid":"bro_1", "source.type":"bro"},{"guid":"bro_2", "source.type":"bro"},{"guid":"snort_1", "source.type":"snort"}],"average":"5.0","min":"0.0","median":"5.0","max":"10.0","count":"3.0","sum":"15.0"} * ] */ @Multiline @@ -163,58 +165,32 @@ public class MetaAlertControllerIntegrationTest extends DaoControllerTest { .andExpect(jsonPath("$.results[0].source.count").value(3.0)) .andExpect(jsonPath("$.results[1].source.guid").value("meta_1")) .andExpect(jsonPath("$.results[1].source.count").value(1.0)); + } - result = this.mockMvc.perform( - post(metaalertUrl + "/create") - .with(httpBasic(user, password)).with(csrf()) - .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) - .content(create)); - result.andExpect(status().isOk()); - - // Test that we can find the newly created meta alert by the sub alerts - guid = "bro_1"; - result = this.mockMvc.perform( - post(metaalertUrl + "/searchByAlert") - .with(httpBasic(user, password)).with(csrf()) - .contentType(MediaType.parseMediaType("text/plain;charset=UTF-8")) - .content(guid)); - result.andExpect(status().isOk()) - .andExpect( - content().contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))) - .andExpect(jsonPath("$.total").value(3)) - .andExpect(jsonPath("$.results[0].source.guid").value("meta_3")) - .andExpect(jsonPath("$.results[0].source.count").value(2.0)) - .andExpect(jsonPath("$.results[1].source.guid").value("meta_2")) - .andExpect(jsonPath("$.results[1].source.count").value(3.0)) - .andExpect(jsonPath("$.results[2].source.guid").value("meta_1")) - .andExpect(jsonPath("$.results[2].source.count").value(1.0)); - - guid = "snort_2"; - result = this.mockMvc.perform( - post(metaalertUrl + "/searchByAlert") - .with(httpBasic(user, password)).with(csrf()) - .contentType(MediaType.parseMediaType("text/plain;charset=UTF-8")) - .content(guid)); + @Test + public void shouldCreateMetaAlert() throws Exception { + ResultActions result = this.mockMvc.perform( + post(metaalertUrl + "/create") + .with(httpBasic(user, password)).with(csrf()) + .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) + .content(create)); result.andExpect(status().isOk()) - .andExpect( - content().contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))) - .andExpect(jsonPath("$.total").value(1)) - .andExpect(jsonPath("$.results[0].source.guid").value("meta_3")) - .andExpect(jsonPath("$.results[0].source.count").value(2.0)); + .andExpect(jsonPath("$.guid", notNullValue())) + .andExpect(jsonPath("$.timestamp", greaterThan(0L))) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.timestamp", greaterThan(0L))) + .andExpect(jsonPath("$.document['source.type']").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.status").value("active")) + .andExpect(jsonPath("$.document.groups[0]").value("group_one")) + .andExpect(jsonPath("$.document.groups[1]").value("group_two")) + .andExpect(jsonPath("$.document.metron_alert[0].guid").value("bro_1")) + .andExpect(jsonPath("$.document.metron_alert[1].guid").value("snort_2")); } @Test public void shouldAddRemoveAlerts() throws Exception { - MetaAlertCreateRequest metaAlertCreateRequest = new MetaAlertCreateRequest(); - metaAlertCreateRequest.setGroups(Arrays.asList("group_one", "group_two")); - metaAlertCreateRequest.setAlerts(new ArrayList<GetRequest>() {{ - add(new GetRequest("bro_1", "bro", "bro_index_2017.01.01.01")); - add(new GetRequest("snort_2", "snort", "snort_index_2017.01.01.01")); - }}); - MetaAlertCreateResponse metaAlertCreateResponse = metaAlertService.create(metaAlertCreateRequest); - MetaAlertAddRemoveRequest addRequest = new MetaAlertAddRemoveRequest(); - addRequest.setMetaAlertGuid(metaAlertCreateResponse.getGuid()); + addRequest.setMetaAlertGuid("meta_1"); addRequest.setAlerts(new ArrayList<GetRequest>() {{ add(new GetRequest("bro_2", "bro", "bro_index_2017.01.01.01")); add(new GetRequest("bro_3", "bro", "bro_index_2017.01.01.01")); @@ -225,10 +201,17 @@ public class MetaAlertControllerIntegrationTest extends DaoControllerTest { .with(httpBasic(user, password)).with(csrf()) .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) .content(JSONUtils.INSTANCE.toJSON(addRequest, false))); - result.andExpect(status().isOk()).andExpect(content().string("true")); + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.guid").value("meta_1")) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.metron_alert[0].guid").value("bro_1")) + .andExpect(jsonPath("$.document.metron_alert[1].guid").value("bro_2")) + .andExpect(jsonPath("$.document.metron_alert[2].metaalerts").value("meta_1")) + .andExpect(jsonPath("$.document.metron_alert[2].guid").value("bro_3")) + .andExpect(jsonPath("$.document.metron_alert[2].metaalerts").value("meta_1")); MetaAlertAddRemoveRequest addDuplicateRequest = new MetaAlertAddRemoveRequest(); - addDuplicateRequest.setMetaAlertGuid(metaAlertCreateResponse.getGuid()); + addDuplicateRequest.setMetaAlertGuid("meta_1"); addDuplicateRequest.setAlerts(new ArrayList<GetRequest>() {{ add(new GetRequest("bro_1", "bro")); }}); @@ -238,10 +221,17 @@ public class MetaAlertControllerIntegrationTest extends DaoControllerTest { .with(httpBasic(user, password)).with(csrf()) .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) .content(JSONUtils.INSTANCE.toJSON(addDuplicateRequest, false))); - result.andExpect(status().isOk()).andExpect(content().string("false")); + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.guid").value("meta_1")) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.metron_alert[0].guid").value("bro_1")) + .andExpect(jsonPath("$.document.metron_alert[1].guid").value("bro_2")) + .andExpect(jsonPath("$.document.metron_alert[2].metaalerts").value("meta_1")) + .andExpect(jsonPath("$.document.metron_alert[2].guid").value("bro_3")) + .andExpect(jsonPath("$.document.metron_alert[2].metaalerts").value("meta_1")); MetaAlertAddRemoveRequest removeRequest = new MetaAlertAddRemoveRequest(); - removeRequest.setMetaAlertGuid(metaAlertCreateResponse.getGuid()); + removeRequest.setMetaAlertGuid("meta_1"); removeRequest.setAlerts(new ArrayList<GetRequest>() {{ add(new GetRequest("bro_2", "bro")); add(new GetRequest("bro_3", "bro")); @@ -252,12 +242,16 @@ public class MetaAlertControllerIntegrationTest extends DaoControllerTest { .with(httpBasic(user, password)).with(csrf()) .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) .content(JSONUtils.INSTANCE.toJSON(removeRequest, false))); - result.andExpect(status().isOk()).andExpect(content().string("true")); + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.guid").value("meta_1")) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.metron_alert.*", hasSize(equalTo(1)))) + .andExpect(jsonPath("$.document.metron_alert[0].guid").value("bro_1")); MetaAlertAddRemoveRequest removeMissingRequest = new MetaAlertAddRemoveRequest(); - addRequest.setMetaAlertGuid(metaAlertCreateResponse.getGuid()); + removeMissingRequest.setMetaAlertGuid("meta_1"); removeMissingRequest.setAlerts(new ArrayList<GetRequest>() {{ - add(new GetRequest("bro_1", "bro")); + add(new GetRequest("bro_2", "bro")); }}); result = this.mockMvc.perform( @@ -265,31 +259,47 @@ public class MetaAlertControllerIntegrationTest extends DaoControllerTest { .with(httpBasic(user, password)).with(csrf()) .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) .content(JSONUtils.INSTANCE.toJSON(removeMissingRequest, false))); - result.andExpect(status().isOk()).andExpect(content().string("false")); + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.guid").value("meta_1")) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.metron_alert.*", hasSize(equalTo(1)))) + .andExpect(jsonPath("$.document.metron_alert[0].guid").value("bro_1")); + + MetaAlertAddRemoveRequest emptyMetaAlertRequest = new MetaAlertAddRemoveRequest(); + emptyMetaAlertRequest.setMetaAlertGuid("meta_1"); + emptyMetaAlertRequest.setAlerts(new ArrayList<GetRequest>() {{ + add(new GetRequest("bro_1", "bro")); + }}); + + result = this.mockMvc.perform( + post(metaalertUrl + "/remove/alert") + .with(httpBasic(user, password)).with(csrf()) + .contentType(MediaType.parseMediaType("application/json;charset=UTF-8")) + .content(JSONUtils.INSTANCE.toJSON(emptyMetaAlertRequest, false))); + result.andExpect(status().isInternalServerError()) + .andExpect(jsonPath("$.message").value("Removing these alerts will result in an empty meta alert. Empty meta alerts are not allowed.")) + .andExpect(jsonPath("$.fullMessage").value("IllegalStateException: Removing these alerts will result in an empty meta alert. Empty meta alerts are not allowed.")); } @Test public void shouldUpdateStatus() throws Exception { - MetaAlertCreateRequest metaAlertCreateRequest = new MetaAlertCreateRequest(); - metaAlertCreateRequest.setGroups(Arrays.asList("group_one", "group_two")); - metaAlertCreateRequest.setAlerts(new ArrayList<GetRequest>() {{ - add(new GetRequest("bro_1", "bro", "bro_index_2017.01.01.01")); - add(new GetRequest("snort_2", "snort", "snort_index_2017.01.01.01")); - }}); - - MetaAlertCreateResponse metaAlertCreateResponse = metaAlertService.create(metaAlertCreateRequest); - ResultActions result = this.mockMvc.perform( - post(metaalertUrl + "/update/status/" + metaAlertCreateResponse.getGuid() + "/inactive") + post(metaalertUrl + "/update/status/meta_2/inactive") .with(httpBasic(user, password)).with(csrf()) .contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))); - result.andExpect(status().isOk()).andExpect(content().string("true")); + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.guid").value("meta_2")) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.status").value("inactive")); result = this.mockMvc.perform( - post(metaalertUrl + "/update/status/" + metaAlertCreateResponse.getGuid() + "/inactive") + post(metaalertUrl + "/update/status/meta_2/active") .with(httpBasic(user, password)).with(csrf()) .contentType(MediaType.parseMediaType("application/json;charset=UTF-8"))); - result.andExpect(status().isOk()).andExpect(content().string("false")); + result.andExpect(status().isOk()) + .andExpect(jsonPath("$.guid").value("meta_2")) + .andExpect(jsonPath("$.sensorType").value(MetaAlertConstants.METAALERT_TYPE)) + .andExpect(jsonPath("$.document.status").value("active")); } } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java index 59f25f0..9f6e1a1 100644 --- a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java +++ b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchDao.java @@ -138,34 +138,34 @@ public class ElasticsearchDao implements IndexDao { } @Override - public void update(Document update, Optional<String> index) throws IOException { - updateDao.update(update, index); + public Document update(Document update, Optional<String> index) throws IOException { + return updateDao.update(update, index); } @Override - public void batchUpdate(Map<Document, Optional<String>> updates) throws IOException { - updateDao.batchUpdate(updates); + public Map<Document, Optional<String>> batchUpdate(Map<Document, Optional<String>> updates) throws IOException { + return updateDao.batchUpdate(updates); } @Override - public void patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request, Optional<Long> timestamp) + public Document patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request, Optional<Long> timestamp) throws OriginalNotFoundException, IOException { - updateDao.patch(retrieveLatestDao, request, timestamp); + return updateDao.patch(retrieveLatestDao, request, timestamp); } @Override - public void replace(ReplaceRequest request, Optional<Long> timestamp) throws IOException { - updateDao.replace(request, timestamp); + public Document replace(ReplaceRequest request, Optional<Long> timestamp) throws IOException { + return updateDao.replace(request, timestamp); } @Override - public void addCommentToAlert(CommentAddRemoveRequest request) throws IOException { - updateDao.addCommentToAlert(request); + public Document addCommentToAlert(CommentAddRemoveRequest request) throws IOException { + return updateDao.addCommentToAlert(request); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { - updateDao.removeCommentFromAlert(request); + public Document removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { + return updateDao.removeCommentFromAlert(request); } @Override @@ -179,13 +179,13 @@ public class ElasticsearchDao implements IndexDao { } @Override - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - this.updateDao.addCommentToAlert(request, latest); + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + return this.updateDao.addCommentToAlert(request, latest); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - this.updateDao.removeCommentFromAlert(request, latest); + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + return this.updateDao.removeCommentFromAlert(request, latest); } protected Optional<String> getIndexName(String guid, String sensorType) { http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java index 55123a5..fc0b20c 100644 --- a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java +++ b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDao.java @@ -26,7 +26,6 @@ import org.apache.metron.indexing.dao.RetrieveLatestDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertConfig; import org.apache.metron.indexing.dao.metaalert.MetaAlertConstants; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; import org.apache.metron.indexing.dao.metaalert.MetaAlertDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus; import org.apache.metron.indexing.dao.search.FieldType; @@ -182,25 +181,25 @@ public class ElasticsearchMetaAlertDao implements MetaAlertDao { } @Override - public MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request) + public Document createMetaAlert(MetaAlertCreateRequest request) throws InvalidCreateException, IOException { return metaAlertUpdateDao.createMetaAlert(request); } @Override - public boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) + public Document addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) throws IOException { return metaAlertUpdateDao.addAlertsToMetaAlert(metaAlertGuid, alertRequests); } @Override - public boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) + public Document removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) throws IOException { return metaAlertUpdateDao.removeAlertsFromMetaAlert(metaAlertGuid, alertRequests); } @Override - public boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) + public Document updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws IOException { return metaAlertUpdateDao.updateMetaAlertStatus(metaAlertGuid, status); } @@ -216,40 +215,40 @@ public class ElasticsearchMetaAlertDao implements MetaAlertDao { } @Override - public void update(Document update, Optional<String> index) throws IOException { - metaAlertUpdateDao.update(update, index); + public Document update(Document update, Optional<String> index) throws IOException { + return metaAlertUpdateDao.update(update, index); } @Override - public void batchUpdate(Map<Document, Optional<String>> updates) { - metaAlertUpdateDao.batchUpdate(updates); + public Map<Document, Optional<String>> batchUpdate(Map<Document, Optional<String>> updates) { + return metaAlertUpdateDao.batchUpdate(updates); } @Override - public void addCommentToAlert(CommentAddRemoveRequest request) throws IOException { - indexDao.addCommentToAlert(request); + public Document addCommentToAlert(CommentAddRemoveRequest request) throws IOException { + return indexDao.addCommentToAlert(request); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { - indexDao.removeCommentFromAlert(request); + public Document removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { + return indexDao.removeCommentFromAlert(request); } @Override - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - indexDao.addCommentToAlert(request, latest); + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + return indexDao.addCommentToAlert(request, latest); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - indexDao.removeCommentFromAlert(request, latest); + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + return indexDao.removeCommentFromAlert(request, latest); } @Override - public void patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request, + public Document patch(RetrieveLatestDao retrieveLatestDao, PatchRequest request, Optional<Long> timestamp) throws OriginalNotFoundException, IOException { - metaAlertUpdateDao.patch(retrieveLatestDao, request, timestamp); + return metaAlertUpdateDao.patch(retrieveLatestDao, request, timestamp); } public void setPageSize(int pageSize) { http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertUpdateDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertUpdateDao.java b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertUpdateDao.java index bb79b7a..3b67891 100644 --- a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertUpdateDao.java +++ b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertUpdateDao.java @@ -30,7 +30,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; -import java.util.function.Supplier; import java.util.stream.Collectors; import org.apache.lucene.search.join.ScoreMode; import org.apache.metron.common.Constants; @@ -38,8 +37,6 @@ import org.apache.metron.elasticsearch.utils.ElasticsearchUtils; import org.apache.metron.indexing.dao.metaalert.MetaAlertConfig; import org.apache.metron.indexing.dao.metaalert.MetaAlertConstants; import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateRequest; -import org.apache.metron.indexing.dao.metaalert.MetaAlertCreateResponse; -import org.apache.metron.indexing.dao.metaalert.MetaAlertDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertRetrieveLatestDao; import org.apache.metron.indexing.dao.metaalert.MetaAlertStatus; import org.apache.metron.indexing.dao.metaalert.MetaScores; @@ -82,7 +79,7 @@ public class ElasticsearchMetaAlertUpdateDao extends AbstractLuceneMetaAlertUpda @Override @SuppressWarnings("unchecked") - public MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request) + public Document createMetaAlert(MetaAlertCreateRequest request) throws InvalidCreateException, IOException { List<GetRequest> alertRequests = request.getAlerts(); if (request.getAlerts().isEmpty()) { @@ -134,39 +131,14 @@ public class ElasticsearchMetaAlertUpdateDao extends AbstractLuceneMetaAlertUpda // Kick off any updates. update(updates); - MetaAlertCreateResponse createResponse = new MetaAlertCreateResponse(); - createResponse.setCreated(true); - createResponse.setGuid(metaAlert.getGuid()); - return createResponse; + return metaAlert; } catch (IOException ioe) { throw new InvalidCreateException("Unable to create meta alert", ioe); } } - /** - * Adds alerts to a metaalert, based on a list of GetRequests provided for retrieval. - * @param metaAlertGuid The GUID of the metaalert to be given new children. - * @param alertRequests GetRequests for the appropriate alerts to add. - * @return True if metaalert is modified, false otherwise. - */ - public boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) - throws IOException { - - Document metaAlert = retrieveLatestDao - .getLatest(metaAlertGuid, MetaAlertConstants.METAALERT_TYPE); - if (MetaAlertStatus.ACTIVE.getStatusString() - .equals(metaAlert.getDocument().get(MetaAlertConstants.STATUS_FIELD))) { - Iterable<Document> alerts = retrieveLatestDao.getAllLatest(alertRequests); - Map<Document, Optional<String>> updates = buildAddAlertToMetaAlertUpdates(metaAlert, alerts); - update(updates); - return updates.size() != 0; - } else { - throw new IllegalStateException("Adding alerts to an INACTIVE meta alert is not allowed"); - } - } - @Override - public void update(Document update, Optional<String> index) throws IOException { + public Document update(Document update, Optional<String> index) throws IOException { if (MetaAlertConstants.METAALERT_TYPE.equals(update.getSensorType())) { // We've been passed an update to the meta alert. throw new UnsupportedOperationException("Meta alerts cannot be directly updated"); @@ -195,29 +167,31 @@ public class ElasticsearchMetaAlertUpdateDao extends AbstractLuceneMetaAlertUpda // Run the alert's update elasticsearchDao.batchUpdate(updates); + + return update; } } @Override - public void addCommentToAlert(CommentAddRemoveRequest request) throws IOException { - getUpdateDao().addCommentToAlert(request); + public Document addCommentToAlert(CommentAddRemoveRequest request) throws IOException { + return getUpdateDao().addCommentToAlert(request); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { - getUpdateDao().removeCommentFromAlert(request); + public Document removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { + return getUpdateDao().removeCommentFromAlert(request); } @Override - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - getUpdateDao().addCommentToAlert(request, latest); + return getUpdateDao().addCommentToAlert(request, latest); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - getUpdateDao().removeCommentFromAlert(request, latest); + return getUpdateDao().removeCommentFromAlert(request, latest); } /** @@ -243,12 +217,11 @@ public class ElasticsearchMetaAlertUpdateDao extends AbstractLuceneMetaAlertUpda } - protected boolean replaceAlertInMetaAlert(Document metaAlert, Document alert) { + protected void replaceAlertInMetaAlert(Document metaAlert, Document alert) { boolean metaAlertUpdated = removeAlertsFromMetaAlert(metaAlert, Collections.singleton(alert.getGuid())); if (metaAlertUpdated) { addAlertsToMetaAlert(metaAlert, Collections.singleton(alert)); } - return metaAlertUpdated; } } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDao.java b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDao.java index f2b08d2..6843ac7 100644 --- a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDao.java +++ b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDao.java @@ -60,7 +60,7 @@ public class ElasticsearchUpdateDao implements UpdateDao { } @Override - public void update(Document update, Optional<String> index) throws IOException { + public Document update(Document update, Optional<String> index) throws IOException { String indexPostfix = ElasticsearchUtils .getIndexFormat(accessConfig.getGlobalConfigSupplier().get()).format(new Date()); String sensorType = update.getSensorType(); @@ -79,10 +79,11 @@ public class ElasticsearchUpdateDao implements UpdateDao { } catch (Exception e) { throw new IOException(e.getMessage(), e); } + return update; } @Override - public void batchUpdate(Map<Document, Optional<String>> updates) throws IOException { + public Map<Document, Optional<String>> batchUpdate(Map<Document, Optional<String>> updates) throws IOException { String indexPostfix = ElasticsearchUtils .getIndexFormat(accessConfig.getGlobalConfigSupplier().get()).format(new Date()); @@ -108,20 +109,22 @@ public class ElasticsearchUpdateDao implements UpdateDao { throw new IOException( "ElasticsearchDao upsert failed: " + bulkResponse.buildFailureMessage()); } + return updates; } @Override @SuppressWarnings("unchecked") - public void addCommentToAlert(CommentAddRemoveRequest request) throws IOException { + public Document addCommentToAlert(CommentAddRemoveRequest request) throws IOException { Document latest = retrieveLatestDao.getLatest(request.getGuid(), request.getSensorType()); - addCommentToAlert(request, latest); + return addCommentToAlert(request, latest); } @Override @SuppressWarnings("unchecked") - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - if (latest == null) { - return; + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + if (latest == null || latest.getDocument() == null) { + throw new IOException(String.format("Unable to add comment. Document with guid %s cannot be found.", + request.getGuid())); } List<Map<String, Object>> commentsField = (List<Map<String, Object>>) latest.getDocument() .getOrDefault(COMMENTS_FIELD, new ArrayList<>()); @@ -133,25 +136,30 @@ public class ElasticsearchUpdateDao implements UpdateDao { Document newVersion = new Document(latest); newVersion.getDocument().put(COMMENTS_FIELD, originalComments); - update(newVersion, Optional.empty()); + return update(newVersion, Optional.empty()); } @Override @SuppressWarnings("unchecked") - public void removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { + public Document removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { Document latest = retrieveLatestDao.getLatest(request.getGuid(), request.getSensorType()); - removeCommentFromAlert(request, latest); + return removeCommentFromAlert(request, latest); } @Override @SuppressWarnings("unchecked") - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - if (latest == null) { - return; + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + if (latest == null || latest.getDocument() == null) { + throw new IOException(String.format("Unable to remove comment. Document with guid %s cannot be found.", + request.getGuid())); } - List<Map<String, Object>> commentsField = (List<Map<String, Object>>) latest.getDocument() - .getOrDefault(COMMENTS_FIELD, new ArrayList<>()); - List<Map<String, Object>> originalComments = new ArrayList<>(commentsField); + List<Map<String, Object>> commentMap = (List<Map<String, Object>>) latest.getDocument().get(COMMENTS_FIELD); + // Can't remove anything if there's nothing there + if (commentMap == null) { + throw new IOException(String.format("Unable to remove comment. Document with guid %s has no comments.", + request.getGuid())); + } + List<Map<String, Object>> originalComments = new ArrayList<>(commentMap); List<AlertComment> alertComments = new ArrayList<>(); for (Map<String, Object> commentRaw : originalComments) { @@ -170,7 +178,7 @@ public class ElasticsearchUpdateDao implements UpdateDao { newVersion.getDocument().remove(COMMENTS_FIELD); } - update(newVersion, Optional.empty()); + return update(newVersion, Optional.empty()); } protected String getIndexName(Document update, Optional<String> index, String indexPostFix) { http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java index b1da2a4..cabb992 100644 --- a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java +++ b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchMetaAlertDaoTest.java @@ -19,8 +19,6 @@ package org.apache.metron.elasticsearch.dao; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -44,13 +42,6 @@ import org.apache.metron.indexing.dao.update.Document; import org.elasticsearch.index.IndexNotFoundException; import org.junit.Test; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; - import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; @@ -88,11 +79,13 @@ public class ElasticsearchMetaAlertDaoTest { } @Override - public void update(Document update, Optional<String> index) { + public Document update(Document update, Optional<String> index) { + return update; } @Override - public void batchUpdate(Map<Document, Optional<String>> updates) { + public Map<Document, Optional<String>> batchUpdate(Map<Document, Optional<String>> updates) { + return updates; } @Override @@ -101,19 +94,23 @@ public class ElasticsearchMetaAlertDaoTest { } @Override - public void addCommentToAlert(CommentAddRemoveRequest request) { + public Document addCommentToAlert(CommentAddRemoveRequest request) { + return null; } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request) { + public Document removeCommentFromAlert(CommentAddRemoveRequest request) { + return null; } @Override - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) { + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) { + return null; } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) { + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) { + return null; } }; ElasticsearchMetaAlertDao metaAlertDao = new ElasticsearchMetaAlertDao(); http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDaoTest.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDaoTest.java b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDaoTest.java new file mode 100644 index 0000000..3b48a60 --- /dev/null +++ b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/dao/ElasticsearchUpdateDaoTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package org.apache.metron.elasticsearch.dao; + +import org.apache.metron.indexing.dao.AccessConfig; +import org.apache.metron.indexing.dao.UpdateDaoTest; +import org.apache.metron.indexing.dao.update.UpdateDao; +import org.elasticsearch.client.transport.TransportClient; +import org.junit.Before; + +import static org.mockito.Mockito.mock; + +/** + * This class returns the ElasticsearchUpdateDao implementation to be used in UpdateDaoTest. UpdateDaoTest contains a + * common set of tests that all Dao implementations must pass. + */ +public class ElasticsearchUpdateDaoTest extends UpdateDaoTest { + + private TransportClient client; + private AccessConfig accessConfig; + private ElasticsearchRetrieveLatestDao retrieveLatestDao; + private ElasticsearchUpdateDao updateDao; + + @Before + public void setup() { + client = mock(TransportClient.class); + accessConfig = new AccessConfig(); + retrieveLatestDao = mock(ElasticsearchRetrieveLatestDao.class); + updateDao = new ElasticsearchUpdateDao(client, accessConfig, retrieveLatestDao); + } + + @Override + public UpdateDao getUpdateDao() { + return updateDao; + } +} http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/HBaseDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/HBaseDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/HBaseDao.java index 6c646de..71d0544 100644 --- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/HBaseDao.java +++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/HBaseDao.java @@ -238,13 +238,14 @@ public class HBaseDao implements IndexDao { } @Override - public synchronized void update(Document update, Optional<String> index) throws IOException { + public synchronized Document update(Document update, Optional<String> index) throws IOException { Put put = buildPut(update); getTableInterface().put(put); + return update; } @Override - public void batchUpdate(Map<Document, Optional<String>> updates) throws IOException { + public Map<Document, Optional<String>> batchUpdate(Map<Document, Optional<String>> updates) throws IOException { List<Put> puts = new ArrayList<>(); for (Map.Entry<Document, Optional<String>> updateEntry : updates.entrySet()) { Document update = updateEntry.getKey(); @@ -253,6 +254,7 @@ public class HBaseDao implements IndexDao { puts.add(put); } getTableInterface().put(puts); + return updates; } protected Get buildGet(GetRequest getRequest) throws IOException { @@ -280,16 +282,17 @@ public class HBaseDao implements IndexDao { @Override @SuppressWarnings("unchecked") - public void addCommentToAlert(CommentAddRemoveRequest request) throws IOException { + public Document addCommentToAlert(CommentAddRemoveRequest request) throws IOException { Document latest = getLatest(request.getGuid(), request.getSensorType()); - addCommentToAlert(request, latest); + return addCommentToAlert(request, latest); } @Override @SuppressWarnings("unchecked") - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { if (latest == null || latest.getDocument() == null) { - throw new IOException("Unable to add comment to document that doesn't exist"); + throw new IOException(String.format("Unable to add comment. Document with guid %s cannot be found.", + request.getGuid())); } List<Map<String, Object>> comments = (List<Map<String, Object>>) latest.getDocument() @@ -309,28 +312,30 @@ public class HBaseDao implements IndexDao { Document newVersion = new Document(latest); newVersion.getDocument().put(COMMENTS_FIELD, commentsMap); - update(newVersion, Optional.empty()); + return update(newVersion, Optional.empty()); } @Override @SuppressWarnings("unchecked") - public void removeCommentFromAlert(CommentAddRemoveRequest request) + public Document removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { Document latest = getLatest(request.getGuid(), request.getSensorType()); - removeCommentFromAlert(request, latest); + return removeCommentFromAlert(request, latest); } @Override @SuppressWarnings("unchecked") - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { if (latest == null || latest.getDocument() == null) { - throw new IOException("Unable to remove comment document that doesn't exist"); + throw new IOException(String.format("Unable to remove comment. Document with guid %s cannot be found.", + request.getGuid())); } List<Map<String, Object>> commentMap = (List<Map<String, Object>>) latest.getDocument().get(COMMENTS_FIELD); // Can't remove anything if there's nothing there if (commentMap == null) { - return; + throw new IOException(String.format("Unable to remove comment. Document with guid %s has no comments.", + request.getGuid())); } List<Map<String, Object>> originalComments = new ArrayList<>(commentMap); List<AlertComment> comments = new ArrayList<>(); @@ -349,6 +354,6 @@ public class HBaseDao implements IndexDao { newVersion.getDocument().remove(COMMENTS_FIELD); } - update(newVersion, Optional.empty()); + return update(newVersion, Optional.empty()); } } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MultiIndexDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MultiIndexDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MultiIndexDao.java index 420c775..c3e2108 100644 --- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MultiIndexDao.java +++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/MultiIndexDao.java @@ -25,7 +25,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; @@ -58,7 +57,7 @@ public class MultiIndexDao implements IndexDao { } @Override - public void update(final Document update, Optional<String> index) throws IOException { + public Document update(final Document update, Optional<String> index) throws IOException { List<String> exceptions = indices.parallelStream().map(dao -> { try { @@ -71,10 +70,11 @@ public class MultiIndexDao implements IndexDao { if(exceptions.size() > 0) { throw new IOException(Joiner.on("\n").join(exceptions)); } + return update; } @Override - public void batchUpdate(Map<Document, Optional<String>> updates) throws IOException { + public Map<Document, Optional<String>> batchUpdate(Map<Document, Optional<String>> updates) throws IOException { List<String> exceptions = indices.parallelStream().map(dao -> { try { @@ -87,6 +87,7 @@ public class MultiIndexDao implements IndexDao { if (exceptions.size() > 0) { throw new IOException(Joiner.on("\n").join(exceptions)); } + return updates; } @Override @@ -101,51 +102,62 @@ public class MultiIndexDao implements IndexDao { } @Override - public void addCommentToAlert(CommentAddRemoveRequest request) throws IOException { + public Document addCommentToAlert(CommentAddRemoveRequest request) throws IOException { Document latest = getLatest(request.getGuid(), request.getSensorType()); - addCommentToAlert(request, latest); + return addCommentToAlert(request, latest); } - + /** + * Adds comments to an alert. Updates are written to each Dao in parallel with the assumption that all updates + * are identical. The first update to be applied is returned as the current version of the alert with comments added. + * @param request Request to add comments + * @param latest The latest version of the alert the comments will be added to. + * @return The complete alert document with comments added. + * @throws IOException + */ @Override - public void addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - List<String> exceptions = - indices.parallelStream().map(dao -> { - try { - dao.addCommentToAlert(request, latest); - return null; - } catch (Throwable e) { - return dao.getClass() + ": " + e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e); - } - }).filter(Objects::nonNull).collect(Collectors.toList()); - if (exceptions.size() > 0) { - throw new IOException(Joiner.on("\n").join(exceptions)); - } + public Document addCommentToAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + List<DocumentContainer> output = + indices.parallelStream().map(dao -> { + try { + return new DocumentContainer(dao.addCommentToAlert(request, latest)); + } catch (Throwable e) { + return new DocumentContainer(e); + } + }).collect(Collectors.toList()); + + return getLatestDocument(output); } @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { + public Document removeCommentFromAlert(CommentAddRemoveRequest request) throws IOException { Document latest = getLatest(request.getGuid(), request.getSensorType()); - removeCommentFromAlert(request, latest); + return removeCommentFromAlert(request, latest); } + /** + * Removes comments from an alert. Updates are written to each Dao in parallel with the assumption that all updates + * are identical. The first update to be applied is returned as the current version of the alert with comments removed. + * @param request Request to remove comments + * @param latest The latest version of the alert the comments will be removed from. + * @return The complete alert document with comments removed. + * @throws IOException + */ @Override - public void removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { - List<String> exceptions = - indices.parallelStream().map(dao -> { - try { - dao.removeCommentFromAlert(request, latest); - return null; - } catch (Throwable e) { - return dao.getClass() + ": " + e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e); - } - }).filter(Objects::nonNull).collect(Collectors.toList()); - if (exceptions.size() > 0) { - throw new IOException(Joiner.on("\n").join(exceptions)); - } + public Document removeCommentFromAlert(CommentAddRemoveRequest request, Document latest) throws IOException { + List<DocumentContainer> output = + indices.parallelStream().map(dao -> { + try { + return new DocumentContainer(dao.removeCommentFromAlert(request, latest)); + } catch (Throwable e) { + return new DocumentContainer(e); + } + }).collect(Collectors.toList()); + + return getLatestDocument(output); } - private static class DocumentContainer { + protected static class DocumentContainer { private Optional<Document> d = Optional.empty(); private Optional<Throwable> t = Optional.empty(); public DocumentContainer(Document d) { @@ -214,7 +226,6 @@ public class MultiIndexDao implements IndexDao { @Override public Document getLatest(final String guid, String sensorType) throws IOException { - Document ret = null; List<DocumentContainer> output = indices.parallelStream().map(dao -> { try { @@ -224,25 +235,7 @@ public class MultiIndexDao implements IndexDao { } }).collect(Collectors.toList()); - List<String> error = new ArrayList<>(); - for(DocumentContainer dc : output) { - if(dc.getException().isPresent()) { - Throwable e = dc.getException().get(); - error.add(e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e)); - } - else { - if(dc.getDocument().isPresent()) { - Document d = dc.getDocument().get(); - if(ret == null || ret.getTimestamp() < d.getTimestamp()) { - ret = d; - } - } - } - } - if(error.size() > 0) { - throw new IOException(Joiner.on("\n").join(error)); - } - return ret; + return getLatestDocument(output); } @Override @@ -282,4 +275,39 @@ public class MultiIndexDao implements IndexDao { public List<IndexDao> getIndices() { return indices; } + + /** + * Returns the most recent {@link Document} from a list of {@link DocumentContainer}s. + * + * @param documentContainers A list of containers; each retrieved from a separate index. + * @return The latest {@link Document} found. + * @throws IOException If any of the {@link DocumentContainer}s contain an exception. + */ + private Document getLatestDocument(List<DocumentContainer> documentContainers) throws IOException { + Document latestDocument = null; + List<String> error = new ArrayList<>(); + + for(DocumentContainer dc : documentContainers) { + if(dc.getException().isPresent()) { + // collect each exception; multiple can occur, one in each index + Throwable e = dc.getException().get(); + error.add(e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e)); + + } else if(dc.getDocument().isPresent()) { + Document d = dc.getDocument().get(); + // is this the latest document so far? + if(latestDocument == null || latestDocument.getTimestamp() < d.getTimestamp()) { + latestDocument = d; + } + + } else { + // no document was found in the index + } + } + if(error.size() > 0) { + // report all of the errors encountered + throw new IOException(Joiner.on("\n").join(error)); + } + return latestDocument; + } } http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertCreateResponse.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertCreateResponse.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertCreateResponse.java deleted file mode 100644 index 0bdf332..0000000 --- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertCreateResponse.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ - -package org.apache.metron.indexing.dao.metaalert; - -public class MetaAlertCreateResponse { - private boolean created; - private String guid; - - public boolean isCreated() { - return created; - } - - public void setCreated(boolean created) { - this.created = created; - } - - public String getGuid() { - return guid; - } - - public void setGuid(String guid) { - this.guid = guid; - } -} http://git-wip-us.apache.org/repos/asf/metron/blob/de533063/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java ---------------------------------------------------------------------- diff --git a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java index f4374b4..4b22656 100644 --- a/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java +++ b/metron-platform/metron-indexing/src/main/java/org/apache/metron/indexing/dao/metaalert/MetaAlertUpdateDao.java @@ -59,31 +59,31 @@ public interface MetaAlertUpdateDao extends UpdateDao { * retrieved using the DAO abstractions. * * @param request A request object containing get requests for alerts to be added and a list of groups - * @return A response indicating success or failure along with the GUID of the new meta alert + * @return The complete document of the created metaalert. * @throws InvalidCreateException If a malformed create request is provided * @throws IOException If a problem occurs during communication */ - MetaAlertCreateResponse createMetaAlert(MetaAlertCreateRequest request) + Document createMetaAlert(MetaAlertCreateRequest request) throws InvalidCreateException, IOException; /** * Adds alerts to a metaalert, based on a list of GetRequests provided for retrieval. * @param metaAlertGuid The GUID of the metaalert to be given new children. * @param alertRequests GetRequests for the appropriate alerts to add. - * @return True if metaalert is modified, false otherwise. + * @return The complete metaalert document with the alerts added. */ - boolean addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) - throws IOException; + Document addAlertsToMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) + throws IOException, IllegalStateException; /** * Removes alerts from a metaalert * @param metaAlertGuid The metaalert guid to be affected. * @param alertRequests A list of GetReqests that will provide the alerts to remove - * @return True if there are updates, false otherwise + * @return The complete metaalert document with the alerts removed. * @throws IOException If an error is thrown during retrieal. */ - boolean removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) - throws IOException; + Document removeAlertsFromMetaAlert(String metaAlertGuid, List<GetRequest> alertRequests) + throws IOException, IllegalStateException; /** * Removes a metaalert link from a given alert. An nonexistent link performs no change. @@ -115,10 +115,10 @@ public interface MetaAlertUpdateDao extends UpdateDao { * * @param metaAlertGuid The GUID of the meta alert * @param status A status value of 'active' or 'inactive' - * @return True or false depending on if the status was changed + * @return The complete metaalert document with the updated status. * @throws IOException if an error occurs during the update. */ - boolean updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) + Document updateMetaAlertStatus(String metaAlertGuid, MetaAlertStatus status) throws IOException; /**
