Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added a setup endpoint GET _zentity/_setup to create the .zentity-mod…
…els index manually. Allows number_of_shards and number_of_replicas to be specified in the URI parameters.
  • Loading branch information
davemoore- committed May 17, 2018
1 parent ccd995a commit 79a00e3
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 52 deletions.
96 changes: 44 additions & 52 deletions src/main/java/org/elasticsearch/plugin/zentity/ModelsAction.java
Expand Up @@ -2,6 +2,7 @@

import io.zentity.model.Model;
import io.zentity.model.ValidationException;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
import org.elasticsearch.action.delete.DeleteRequestBuilder;
Expand Down Expand Up @@ -34,30 +35,7 @@

public class ModelsAction extends BaseRestHandler {

public static final String INDEX = ".zentity-models";
public static final String INDEX_MAPPING = "{\n" +
" \"doc\": {\n" +
" \"dynamic\": \"strict\",\n" +
" \"properties\": {\n" +
" \"attributes\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" },\n" +
" \"resolvers\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" },\n" +
" \"matchers\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" },\n" +
" \"indices\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
public static final String INDEX_NAME = ".zentity-models";

@Inject
public ModelsAction(Settings settings, RestController controller) {
Expand All @@ -69,41 +47,41 @@ public ModelsAction(Settings settings, RestController controller) {
controller.registerHandler(DELETE, "_zentity/models/{entity_type}", this);
}

public static void createIndex(NodeClient client) {
client.admin().indices().prepareCreate(INDEX)
.setSettings(Settings.builder()
.put("index.number_of_shards", 1)
.put("index.number_of_replicas", 1)
)
.addMapping("doc", INDEX_MAPPING, XContentType.JSON)
.get();
}

/**
* Check if the .zentity-models index exists, and if it doesn't, then create it.
*
* @param client The client that will communicate with Elasticsearch.
* @throws ForbiddenException
*/
public static void ensureIndex(NodeClient client) {
IndicesExistsRequestBuilder request = client.admin().indices().prepareExists(INDEX);
IndicesExistsResponse response = request.get();
if (!response.isExists())
createIndex(client);
public static void ensureIndex(NodeClient client) throws ForbiddenException {
try {
IndicesExistsRequestBuilder request = client.admin().indices().prepareExists(INDEX_NAME);
IndicesExistsResponse response = request.get();
if (!response.isExists())
SetupAction.createIndex(client);
} catch (ElasticsearchSecurityException se) {
throw new ForbiddenException("The .zentity-models index does not exist and you do not have the 'create_index' privilege. An authorized user must create the index by submitting: POST _zentity/_setup");
}
}

/**
* Retrieve all entity models.
*
* @param client The client that will communicate with Elasticsearch.
* @return The response from Elasticsearch.
* @throws ForbiddenException
*/
public static SearchResponse getEntityModels(NodeClient client) {
SearchRequestBuilder request = client.prepareSearch(INDEX);
public static SearchResponse getEntityModels(NodeClient client) throws ForbiddenException {
SearchRequestBuilder request = client.prepareSearch(INDEX_NAME);
request.setSize(10000);
try {
return request.get();
} catch (IndexNotFoundException e) {
createIndex(client);
try {
SetupAction.createIndex(client);
} catch (ElasticsearchSecurityException se) {
throw new ForbiddenException("The .zentity-models index does not exist and you do not have the 'create_index' privilege. An authorized user must create the index by submitting: POST _zentity/_setup");
}
return request.get();
}
}
Expand All @@ -114,13 +92,18 @@ public static SearchResponse getEntityModels(NodeClient client) {
* @param entityType The entity type.
* @param client The client that will communicate with Elasticsearch.
* @return The response from Elasticsearch.
* @throws ForbiddenException
*/
public static GetResponse getEntityModel(String entityType, NodeClient client) {
GetRequestBuilder request = client.prepareGet(INDEX, "doc", entityType);
public static GetResponse getEntityModel(String entityType, NodeClient client) throws ForbiddenException {
GetRequestBuilder request = client.prepareGet(INDEX_NAME, "doc", entityType);
try {
return request.get();
} catch (IndexNotFoundException e) {
createIndex(client);
try {
SetupAction.createIndex(client);
} catch (ElasticsearchSecurityException se) {
throw new ForbiddenException("The .zentity-models index does not exist and you do not have the 'create_index' privilege. An authorized user must create the index by submitting: POST _zentity/_setup");
}
return request.get();
}
}
Expand All @@ -132,10 +115,11 @@ public static GetResponse getEntityModel(String entityType, NodeClient client) {
* @param requestBody The request body.
* @param client The client that will communicate with Elasticsearch.
* @return The response from Elasticsearch.
* @throws ForbiddenException
*/
public static IndexResponse indexEntityModel(String entityType, String requestBody, NodeClient client) {
public static IndexResponse indexEntityModel(String entityType, String requestBody, NodeClient client) throws ForbiddenException {
ensureIndex(client);
IndexRequestBuilder request = client.prepareIndex(INDEX, "doc", entityType);
IndexRequestBuilder request = client.prepareIndex(INDEX_NAME, "doc", entityType);
request.setSource(requestBody, XContentType.JSON).setCreate(true).setRefreshPolicy("wait_for");
return request.get();
}
Expand All @@ -147,10 +131,11 @@ public static IndexResponse indexEntityModel(String entityType, String requestBo
* @param requestBody The request body.
* @param client The client that will communicate with Elasticsearch.
* @return The response from Elasticsearch.
* @throws ForbiddenException
*/
public static IndexResponse updateEntityModel(String entityType, String requestBody, NodeClient client) {
public static IndexResponse updateEntityModel(String entityType, String requestBody, NodeClient client) throws ForbiddenException {
ensureIndex(client);
IndexRequestBuilder request = client.prepareIndex(INDEX, "doc", entityType);
IndexRequestBuilder request = client.prepareIndex(INDEX_NAME, "doc", entityType);
request.setSource(requestBody, XContentType.JSON).setCreate(false).setRefreshPolicy("wait_for");
return request.get();
}
Expand All @@ -161,14 +146,19 @@ public static IndexResponse updateEntityModel(String entityType, String requestB
* @param entityType The entity type.
* @param client The client that will communicate with Elasticsearch.
* @return The response from Elasticsearch.
* @throws ForbiddenException
*/
private static DeleteResponse deleteEntityModel(String entityType, NodeClient client) {
DeleteRequestBuilder request = client.prepareDelete(INDEX, "doc", entityType);
private static DeleteResponse deleteEntityModel(String entityType, NodeClient client) throws ForbiddenException {
DeleteRequestBuilder request = client.prepareDelete(INDEX_NAME, "doc", entityType);
request.setRefreshPolicy("wait_for");
try {
return request.get();
} catch (IndexNotFoundException e) {
createIndex(client);
try {
SetupAction.createIndex(client);
} catch (ElasticsearchSecurityException se) {
throw new ForbiddenException("The .zentity-models index does not exist and you do not have the 'create_index' privilege. An authorized user must create the index by submitting: POST _zentity/_setup");
}
return request.get();
}
}
Expand Down Expand Up @@ -257,6 +247,8 @@ protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient

} catch (ValidationException e) {
channel.sendResponse(new BytesRestResponse(channel, RestStatus.BAD_REQUEST, e));
} catch (ForbiddenException e) {
channel.sendResponse(new BytesRestResponse(channel, RestStatus.FORBIDDEN, e));
} catch (NotImplementedException e) {
channel.sendResponse(new BytesRestResponse(channel, RestStatus.NOT_IMPLEMENTED, e));
}
Expand Down
115 changes: 115 additions & 0 deletions src/main/java/org/elasticsearch/plugin/zentity/SetupAction.java
@@ -0,0 +1,115 @@
package org.elasticsearch.plugin.zentity;

import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestStatus;

import static org.elasticsearch.rest.RestRequest.Method;
import static org.elasticsearch.rest.RestRequest.Method.POST;

public class SetupAction extends BaseRestHandler {

public static final int DEFAULT_NUMBER_OF_SHARDS = 1;
public static final int DEFAULT_NUMBER_OF_REPLICAS = 1;
public static final String INDEX_MAPPING = "{\n" +
" \"doc\": {\n" +
" \"dynamic\": \"strict\",\n" +
" \"properties\": {\n" +
" \"attributes\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" },\n" +
" \"resolvers\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" },\n" +
" \"matchers\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" },\n" +
" \"indices\": {\n" +
" \"type\": \"object\",\n" +
" \"enabled\": false\n" +
" }\n" +
" }\n" +
" }\n" +
"}";

@Inject
public SetupAction(Settings settings, RestController controller) {
super(settings);
controller.registerHandler(POST, "_zentity/_setup", this);
}

/**
* Create the .zentity-models index.
*
* @param client The client that will communicate with Elasticsearch.
* @param numberOfShards The value of index.number_of_shards.
* @param numberOfReplicas The value of index.number_of_replicas.
* @return
*/
public static CreateIndexResponse createIndex(NodeClient client, int numberOfShards, int numberOfReplicas) {
return client.admin().indices().prepareCreate(ModelsAction.INDEX_NAME)
.setSettings(Settings.builder()
.put("index.number_of_shards", numberOfShards)
.put("index.number_of_replicas", numberOfReplicas)
)
.addMapping("doc", INDEX_MAPPING, XContentType.JSON)
.get();
}

/**
* Create the .zentity-models index using the default index settings.
*
* @param client The client that will communicate with Elasticsearch.
* @return
*/
public static CreateIndexResponse createIndex(NodeClient client) {
return createIndex(client, DEFAULT_NUMBER_OF_SHARDS, DEFAULT_NUMBER_OF_REPLICAS);
}

@Override
public String getName() {
return "zentity_setup_action";
}

@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {

// Parse request
Boolean pretty = restRequest.paramAsBoolean("pretty", false);
int numberOfShards = restRequest.paramAsInt("number_of_shards", 1);
int numberOfReplicas = restRequest.paramAsInt("number_of_replicas", 1);
Method method = restRequest.method();

return channel -> {
try {
if (method == POST) {

CreateIndexResponse response = createIndex(client, numberOfShards, numberOfReplicas);
XContentBuilder content = XContentFactory.jsonBuilder();
if (pretty)
content.prettyPrint();
content = response.toXContent(content, ToXContent.EMPTY_PARAMS);
channel.sendResponse(new BytesRestResponse(RestStatus.OK, content));

} else {
throw new NotImplementedException("Method and endpoint not implemented.");
}
} catch (NotImplementedException e) {
channel.sendResponse(new BytesRestResponse(channel, RestStatus.NOT_IMPLEMENTED, e));
}
};
}
}
@@ -1,5 +1,6 @@
package org.elasticsearch.plugin.zentity;

import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.node.DiscoveryNodes;
import org.elasticsearch.common.settings.ClusterSettings;
Expand Down Expand Up @@ -30,6 +31,12 @@ class NotImplementedException extends Exception {
}
}

class ForbiddenException extends ElasticsearchSecurityException {
public ForbiddenException(String message) {
super(message);
}
}

public class ZentityPlugin extends Plugin implements ActionPlugin {

private static final Properties properties = new Properties();
Expand Down Expand Up @@ -66,6 +73,7 @@ public List<RestHandler> getRestHandlers(
new HomeAction(settings, restController);
new ModelsAction(settings, restController);
new ResolutionAction(settings, restController);
new SetupAction(settings, restController);
}};
return handlers;
}
Expand Down

0 comments on commit 79a00e3

Please sign in to comment.