Skip to content

Commit 79a00e3

Browse files
committed
Added a setup endpoint GET _zentity/_setup to create the .zentity-models index manually. Allows number_of_shards and number_of_replicas to be specified in the URI parameters.
1 parent ccd995a commit 79a00e3

File tree

3 files changed

+167
-52
lines changed

3 files changed

+167
-52
lines changed

src/main/java/org/elasticsearch/plugin/zentity/ModelsAction.java

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import io.zentity.model.Model;
44
import io.zentity.model.ValidationException;
5+
import org.elasticsearch.ElasticsearchSecurityException;
56
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequestBuilder;
67
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse;
78
import org.elasticsearch.action.delete.DeleteRequestBuilder;
@@ -34,30 +35,7 @@
3435

3536
public class ModelsAction extends BaseRestHandler {
3637

37-
public static final String INDEX = ".zentity-models";
38-
public static final String INDEX_MAPPING = "{\n" +
39-
" \"doc\": {\n" +
40-
" \"dynamic\": \"strict\",\n" +
41-
" \"properties\": {\n" +
42-
" \"attributes\": {\n" +
43-
" \"type\": \"object\",\n" +
44-
" \"enabled\": false\n" +
45-
" },\n" +
46-
" \"resolvers\": {\n" +
47-
" \"type\": \"object\",\n" +
48-
" \"enabled\": false\n" +
49-
" },\n" +
50-
" \"matchers\": {\n" +
51-
" \"type\": \"object\",\n" +
52-
" \"enabled\": false\n" +
53-
" },\n" +
54-
" \"indices\": {\n" +
55-
" \"type\": \"object\",\n" +
56-
" \"enabled\": false\n" +
57-
" }\n" +
58-
" }\n" +
59-
" }\n" +
60-
"}";
38+
public static final String INDEX_NAME = ".zentity-models";
6139

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

72-
public static void createIndex(NodeClient client) {
73-
client.admin().indices().prepareCreate(INDEX)
74-
.setSettings(Settings.builder()
75-
.put("index.number_of_shards", 1)
76-
.put("index.number_of_replicas", 1)
77-
)
78-
.addMapping("doc", INDEX_MAPPING, XContentType.JSON)
79-
.get();
80-
}
81-
8250
/**
8351
* Check if the .zentity-models index exists, and if it doesn't, then create it.
8452
*
8553
* @param client The client that will communicate with Elasticsearch.
54+
* @throws ForbiddenException
8655
*/
87-
public static void ensureIndex(NodeClient client) {
88-
IndicesExistsRequestBuilder request = client.admin().indices().prepareExists(INDEX);
89-
IndicesExistsResponse response = request.get();
90-
if (!response.isExists())
91-
createIndex(client);
56+
public static void ensureIndex(NodeClient client) throws ForbiddenException {
57+
try {
58+
IndicesExistsRequestBuilder request = client.admin().indices().prepareExists(INDEX_NAME);
59+
IndicesExistsResponse response = request.get();
60+
if (!response.isExists())
61+
SetupAction.createIndex(client);
62+
} catch (ElasticsearchSecurityException se) {
63+
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");
64+
}
9265
}
9366

9467
/**
9568
* Retrieve all entity models.
9669
*
9770
* @param client The client that will communicate with Elasticsearch.
9871
* @return The response from Elasticsearch.
72+
* @throws ForbiddenException
9973
*/
100-
public static SearchResponse getEntityModels(NodeClient client) {
101-
SearchRequestBuilder request = client.prepareSearch(INDEX);
74+
public static SearchResponse getEntityModels(NodeClient client) throws ForbiddenException {
75+
SearchRequestBuilder request = client.prepareSearch(INDEX_NAME);
10276
request.setSize(10000);
10377
try {
10478
return request.get();
10579
} catch (IndexNotFoundException e) {
106-
createIndex(client);
80+
try {
81+
SetupAction.createIndex(client);
82+
} catch (ElasticsearchSecurityException se) {
83+
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");
84+
}
10785
return request.get();
10886
}
10987
}
@@ -114,13 +92,18 @@ public static SearchResponse getEntityModels(NodeClient client) {
11492
* @param entityType The entity type.
11593
* @param client The client that will communicate with Elasticsearch.
11694
* @return The response from Elasticsearch.
95+
* @throws ForbiddenException
11796
*/
118-
public static GetResponse getEntityModel(String entityType, NodeClient client) {
119-
GetRequestBuilder request = client.prepareGet(INDEX, "doc", entityType);
97+
public static GetResponse getEntityModel(String entityType, NodeClient client) throws ForbiddenException {
98+
GetRequestBuilder request = client.prepareGet(INDEX_NAME, "doc", entityType);
12099
try {
121100
return request.get();
122101
} catch (IndexNotFoundException e) {
123-
createIndex(client);
102+
try {
103+
SetupAction.createIndex(client);
104+
} catch (ElasticsearchSecurityException se) {
105+
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");
106+
}
124107
return request.get();
125108
}
126109
}
@@ -132,10 +115,11 @@ public static GetResponse getEntityModel(String entityType, NodeClient client) {
132115
* @param requestBody The request body.
133116
* @param client The client that will communicate with Elasticsearch.
134117
* @return The response from Elasticsearch.
118+
* @throws ForbiddenException
135119
*/
136-
public static IndexResponse indexEntityModel(String entityType, String requestBody, NodeClient client) {
120+
public static IndexResponse indexEntityModel(String entityType, String requestBody, NodeClient client) throws ForbiddenException {
137121
ensureIndex(client);
138-
IndexRequestBuilder request = client.prepareIndex(INDEX, "doc", entityType);
122+
IndexRequestBuilder request = client.prepareIndex(INDEX_NAME, "doc", entityType);
139123
request.setSource(requestBody, XContentType.JSON).setCreate(true).setRefreshPolicy("wait_for");
140124
return request.get();
141125
}
@@ -147,10 +131,11 @@ public static IndexResponse indexEntityModel(String entityType, String requestBo
147131
* @param requestBody The request body.
148132
* @param client The client that will communicate with Elasticsearch.
149133
* @return The response from Elasticsearch.
134+
* @throws ForbiddenException
150135
*/
151-
public static IndexResponse updateEntityModel(String entityType, String requestBody, NodeClient client) {
136+
public static IndexResponse updateEntityModel(String entityType, String requestBody, NodeClient client) throws ForbiddenException {
152137
ensureIndex(client);
153-
IndexRequestBuilder request = client.prepareIndex(INDEX, "doc", entityType);
138+
IndexRequestBuilder request = client.prepareIndex(INDEX_NAME, "doc", entityType);
154139
request.setSource(requestBody, XContentType.JSON).setCreate(false).setRefreshPolicy("wait_for");
155140
return request.get();
156141
}
@@ -161,14 +146,19 @@ public static IndexResponse updateEntityModel(String entityType, String requestB
161146
* @param entityType The entity type.
162147
* @param client The client that will communicate with Elasticsearch.
163148
* @return The response from Elasticsearch.
149+
* @throws ForbiddenException
164150
*/
165-
private static DeleteResponse deleteEntityModel(String entityType, NodeClient client) {
166-
DeleteRequestBuilder request = client.prepareDelete(INDEX, "doc", entityType);
151+
private static DeleteResponse deleteEntityModel(String entityType, NodeClient client) throws ForbiddenException {
152+
DeleteRequestBuilder request = client.prepareDelete(INDEX_NAME, "doc", entityType);
167153
request.setRefreshPolicy("wait_for");
168154
try {
169155
return request.get();
170156
} catch (IndexNotFoundException e) {
171-
createIndex(client);
157+
try {
158+
SetupAction.createIndex(client);
159+
} catch (ElasticsearchSecurityException se) {
160+
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");
161+
}
172162
return request.get();
173163
}
174164
}
@@ -257,6 +247,8 @@ protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient
257247

258248
} catch (ValidationException e) {
259249
channel.sendResponse(new BytesRestResponse(channel, RestStatus.BAD_REQUEST, e));
250+
} catch (ForbiddenException e) {
251+
channel.sendResponse(new BytesRestResponse(channel, RestStatus.FORBIDDEN, e));
260252
} catch (NotImplementedException e) {
261253
channel.sendResponse(new BytesRestResponse(channel, RestStatus.NOT_IMPLEMENTED, e));
262254
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package org.elasticsearch.plugin.zentity;
2+
3+
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
4+
import org.elasticsearch.client.node.NodeClient;
5+
import org.elasticsearch.common.inject.Inject;
6+
import org.elasticsearch.common.settings.Settings;
7+
import org.elasticsearch.common.xcontent.ToXContent;
8+
import org.elasticsearch.common.xcontent.XContentBuilder;
9+
import org.elasticsearch.common.xcontent.XContentFactory;
10+
import org.elasticsearch.common.xcontent.XContentType;
11+
import org.elasticsearch.rest.BaseRestHandler;
12+
import org.elasticsearch.rest.BytesRestResponse;
13+
import org.elasticsearch.rest.RestController;
14+
import org.elasticsearch.rest.RestRequest;
15+
import org.elasticsearch.rest.RestStatus;
16+
17+
import static org.elasticsearch.rest.RestRequest.Method;
18+
import static org.elasticsearch.rest.RestRequest.Method.POST;
19+
20+
public class SetupAction extends BaseRestHandler {
21+
22+
public static final int DEFAULT_NUMBER_OF_SHARDS = 1;
23+
public static final int DEFAULT_NUMBER_OF_REPLICAS = 1;
24+
public static final String INDEX_MAPPING = "{\n" +
25+
" \"doc\": {\n" +
26+
" \"dynamic\": \"strict\",\n" +
27+
" \"properties\": {\n" +
28+
" \"attributes\": {\n" +
29+
" \"type\": \"object\",\n" +
30+
" \"enabled\": false\n" +
31+
" },\n" +
32+
" \"resolvers\": {\n" +
33+
" \"type\": \"object\",\n" +
34+
" \"enabled\": false\n" +
35+
" },\n" +
36+
" \"matchers\": {\n" +
37+
" \"type\": \"object\",\n" +
38+
" \"enabled\": false\n" +
39+
" },\n" +
40+
" \"indices\": {\n" +
41+
" \"type\": \"object\",\n" +
42+
" \"enabled\": false\n" +
43+
" }\n" +
44+
" }\n" +
45+
" }\n" +
46+
"}";
47+
48+
@Inject
49+
public SetupAction(Settings settings, RestController controller) {
50+
super(settings);
51+
controller.registerHandler(POST, "_zentity/_setup", this);
52+
}
53+
54+
/**
55+
* Create the .zentity-models index.
56+
*
57+
* @param client The client that will communicate with Elasticsearch.
58+
* @param numberOfShards The value of index.number_of_shards.
59+
* @param numberOfReplicas The value of index.number_of_replicas.
60+
* @return
61+
*/
62+
public static CreateIndexResponse createIndex(NodeClient client, int numberOfShards, int numberOfReplicas) {
63+
return client.admin().indices().prepareCreate(ModelsAction.INDEX_NAME)
64+
.setSettings(Settings.builder()
65+
.put("index.number_of_shards", numberOfShards)
66+
.put("index.number_of_replicas", numberOfReplicas)
67+
)
68+
.addMapping("doc", INDEX_MAPPING, XContentType.JSON)
69+
.get();
70+
}
71+
72+
/**
73+
* Create the .zentity-models index using the default index settings.
74+
*
75+
* @param client The client that will communicate with Elasticsearch.
76+
* @return
77+
*/
78+
public static CreateIndexResponse createIndex(NodeClient client) {
79+
return createIndex(client, DEFAULT_NUMBER_OF_SHARDS, DEFAULT_NUMBER_OF_REPLICAS);
80+
}
81+
82+
@Override
83+
public String getName() {
84+
return "zentity_setup_action";
85+
}
86+
87+
@Override
88+
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) {
89+
90+
// Parse request
91+
Boolean pretty = restRequest.paramAsBoolean("pretty", false);
92+
int numberOfShards = restRequest.paramAsInt("number_of_shards", 1);
93+
int numberOfReplicas = restRequest.paramAsInt("number_of_replicas", 1);
94+
Method method = restRequest.method();
95+
96+
return channel -> {
97+
try {
98+
if (method == POST) {
99+
100+
CreateIndexResponse response = createIndex(client, numberOfShards, numberOfReplicas);
101+
XContentBuilder content = XContentFactory.jsonBuilder();
102+
if (pretty)
103+
content.prettyPrint();
104+
content = response.toXContent(content, ToXContent.EMPTY_PARAMS);
105+
channel.sendResponse(new BytesRestResponse(RestStatus.OK, content));
106+
107+
} else {
108+
throw new NotImplementedException("Method and endpoint not implemented.");
109+
}
110+
} catch (NotImplementedException e) {
111+
channel.sendResponse(new BytesRestResponse(channel, RestStatus.NOT_IMPLEMENTED, e));
112+
}
113+
};
114+
}
115+
}

src/main/java/org/elasticsearch/plugin/zentity/ZentityPlugin.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.elasticsearch.plugin.zentity;
22

3+
import org.elasticsearch.ElasticsearchSecurityException;
34
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
45
import org.elasticsearch.cluster.node.DiscoveryNodes;
56
import org.elasticsearch.common.settings.ClusterSettings;
@@ -30,6 +31,12 @@ class NotImplementedException extends Exception {
3031
}
3132
}
3233

34+
class ForbiddenException extends ElasticsearchSecurityException {
35+
public ForbiddenException(String message) {
36+
super(message);
37+
}
38+
}
39+
3340
public class ZentityPlugin extends Plugin implements ActionPlugin {
3441

3542
private static final Properties properties = new Properties();
@@ -66,6 +73,7 @@ public List<RestHandler> getRestHandlers(
6673
new HomeAction(settings, restController);
6774
new ModelsAction(settings, restController);
6875
new ResolutionAction(settings, restController);
76+
new SetupAction(settings, restController);
6977
}};
7078
return handlers;
7179
}

0 commit comments

Comments
 (0)