Add Open Index API to the high level REST client (#27574)

Add _open to the high level REST client

Relates to #27205
This commit is contained in:
olcbean 2017-12-07 18:16:03 +01:00 committed by Luca Cavanna
parent b83e14858a
commit bcc33f391f
7 changed files with 238 additions and 14 deletions

View File

@ -25,6 +25,8 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
@ -86,4 +88,27 @@ public final class IndicesClient {
restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, Request::createIndex, CreateIndexResponse::fromXContent, restHighLevelClient.performRequestAsyncAndParseEntity(createIndexRequest, Request::createIndex, CreateIndexResponse::fromXContent,
listener, Collections.emptySet(), headers); listener, Collections.emptySet(), headers);
} }
/**
* Opens an index using the Open Index API
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html">
* Open Index API on elastic.co</a>
*/
public OpenIndexResponse openIndex(OpenIndexRequest openIndexRequest, Header... headers) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(openIndexRequest, Request::openIndex, OpenIndexResponse::fromXContent,
Collections.emptySet(), headers);
}
/**
* Asynchronously opens an index using the Open Index API
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-open-close.html">
* Open Index API on elastic.co</a>
*/
public void openIndexAsync(OpenIndexRequest openIndexRequest, ActionListener<OpenIndexResponse> listener, Header... headers) {
restHighLevelClient.performRequestAsyncAndParseEntity(openIndexRequest, Request::openIndex, OpenIndexResponse::fromXContent,
listener, Collections.emptySet(), headers);
}
} }

View File

@ -31,6 +31,7 @@ import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetRequest;
@ -138,6 +139,19 @@ public final class Request {
return new Request(HttpDelete.METHOD_NAME, endpoint, parameters.getParams(), null); return new Request(HttpDelete.METHOD_NAME, endpoint, parameters.getParams(), null);
} }
static Request openIndex(OpenIndexRequest openIndexRequest) {
String endpoint = endpoint(openIndexRequest.indices(), Strings.EMPTY_ARRAY, "_open");
Params parameters = Params.builder();
parameters.withTimeout(openIndexRequest.timeout());
parameters.withMasterTimeout(openIndexRequest.masterNodeTimeout());
parameters.withWaitForActiveShards(openIndexRequest.waitForActiveShards());
parameters.withIndicesOptions(openIndexRequest.indicesOptions());
return new Request(HttpPost.METHOD_NAME, endpoint, parameters.getParams(), null);
}
static Request createIndex(CreateIndexRequest createIndexRequest) throws IOException { static Request createIndex(CreateIndexRequest createIndexRequest) throws IOException {
String endpoint = endpoint(createIndexRequest.indices(), Strings.EMPTY_ARRAY, ""); String endpoint = endpoint(createIndexRequest.indices(), Strings.EMPTY_ARRAY, "");

View File

@ -26,6 +26,8 @@ import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteRequest;
@ -283,7 +285,7 @@ public class RestHighLevelClient implements Closeable {
* *
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html">Get API on elastic.co</a> * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-get.html">Get API on elastic.co</a>
*/ */
public void getAsync(GetRequest getRequest, ActionListener<GetResponse> listener, Header... headers) { public final void getAsync(GetRequest getRequest, ActionListener<GetResponse> listener, Header... headers) {
performRequestAsyncAndParseEntity(getRequest, Request::get, GetResponse::fromXContent, listener, singleton(404), headers); performRequestAsyncAndParseEntity(getRequest, Request::get, GetResponse::fromXContent, listener, singleton(404), headers);
} }

View File

@ -25,14 +25,21 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse; import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
import java.util.Locale;
import static org.hamcrest.Matchers.equalTo;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS; import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
@ -128,16 +135,73 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
} }
} }
public void testOpenExistingIndex() throws IOException {
String[] indices = randomIndices(1, 5);
for (String index : indices) {
createIndex(index);
closeIndex(index);
ResponseException exception = expectThrows(ResponseException.class, () -> client().performRequest("GET", index + "/_search"));
assertThat(exception.getResponse().getStatusLine().getStatusCode(), equalTo(RestStatus.BAD_REQUEST.getStatus()));
assertThat(exception.getMessage().contains(index), equalTo(true));
}
OpenIndexRequest openIndexRequest = new OpenIndexRequest(indices);
OpenIndexResponse openIndexResponse = execute(openIndexRequest, highLevelClient().indices()::openIndex,
highLevelClient().indices()::openIndexAsync);
assertTrue(openIndexResponse.isAcknowledged());
for (String index : indices) {
Response response = client().performRequest("GET", index + "/_search");
assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus()));
}
}
public void testOpenNonExistentIndex() throws IOException {
String[] nonExistentIndices = randomIndices(1, 5);
for (String nonExistentIndex : nonExistentIndices) {
assertFalse(indexExists(nonExistentIndex));
}
OpenIndexRequest openIndexRequest = new OpenIndexRequest(nonExistentIndices);
ElasticsearchException exception = expectThrows(ElasticsearchException.class,
() -> execute(openIndexRequest, highLevelClient().indices()::openIndex, highLevelClient().indices()::openIndexAsync));
assertEquals(RestStatus.NOT_FOUND, exception.status());
OpenIndexRequest lenientOpenIndexRequest = new OpenIndexRequest(nonExistentIndices);
lenientOpenIndexRequest.indicesOptions(IndicesOptions.lenientExpandOpen());
OpenIndexResponse lenientOpenIndexResponse = execute(lenientOpenIndexRequest, highLevelClient().indices()::openIndex,
highLevelClient().indices()::openIndexAsync);
assertThat(lenientOpenIndexResponse.isAcknowledged(), equalTo(true));
OpenIndexRequest strictOpenIndexRequest = new OpenIndexRequest(nonExistentIndices);
strictOpenIndexRequest.indicesOptions(IndicesOptions.strictExpandOpen());
ElasticsearchException strictException = expectThrows(ElasticsearchException.class,
() -> execute(openIndexRequest, highLevelClient().indices()::openIndex, highLevelClient().indices()::openIndexAsync));
assertEquals(RestStatus.NOT_FOUND, strictException.status());
}
private static String[] randomIndices(int minIndicesNum, int maxIndicesNum) {
int numIndices = randomIntBetween(minIndicesNum, maxIndicesNum);
String[] indices = new String[numIndices];
for (int i = 0; i < numIndices; i++) {
indices[i] = "index-" + randomAlphaOfLengthBetween(2, 5).toLowerCase(Locale.ROOT);
}
return indices;
}
private static void createIndex(String index) throws IOException { private static void createIndex(String index) throws IOException {
Response response = client().performRequest("PUT", index); Response response = client().performRequest("PUT", index);
assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus()));
assertEquals(200, response.getStatusLine().getStatusCode());
} }
private static boolean indexExists(String index) throws IOException { private static boolean indexExists(String index) throws IOException {
Response response = client().performRequest("HEAD", index); Response response = client().performRequest("HEAD", index);
return RestStatus.OK.getStatus() == response.getStatusLine().getStatusCode();
}
return response.getStatusLine().getStatusCode() == 200; private static void closeIndex(String index) throws IOException {
Response response = client().performRequest("POST", index + "/_close");
assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus()));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -27,6 +27,7 @@ import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.DocWriteRequest; import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkShardRequest; import org.elasticsearch.action.bulk.BulkShardRequest;
import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteRequest;
@ -37,7 +38,6 @@ import org.elasticsearch.action.search.MultiSearchRequest;
import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.search.SearchType; import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.master.AcknowledgedRequest; import org.elasticsearch.action.support.master.AcknowledgedRequest;
@ -83,7 +83,6 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.StringJoiner; import java.util.StringJoiner;
import java.util.function.BiConsumer;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -93,10 +92,12 @@ import static org.elasticsearch.client.Request.REQUEST_BODY_CONTENT_TYPE;
import static org.elasticsearch.client.Request.enforceSameContentType; import static org.elasticsearch.client.Request.enforceSameContentType;
import static org.elasticsearch.search.RandomSearchRequestGenerator.randomSearchRequest; import static org.elasticsearch.search.RandomSearchRequestGenerator.randomSearchRequest;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertToXContentEquivalent;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
public class RequestTests extends ESTestCase { public class RequestTests extends ESTestCase {
public void testConstructor() throws Exception { public void testConstructor() {
final String method = randomFrom("GET", "PUT", "POST", "HEAD", "DELETE"); final String method = randomFrom("GET", "PUT", "POST", "HEAD", "DELETE");
final String endpoint = randomAlphaOfLengthBetween(1, 10); final String endpoint = randomAlphaOfLengthBetween(1, 10);
final Map<String, String> parameters = singletonMap(randomAlphaOfLength(5), randomAlphaOfLength(5)); final Map<String, String> parameters = singletonMap(randomAlphaOfLength(5), randomAlphaOfLength(5));
@ -122,7 +123,7 @@ public class RequestTests extends ESTestCase {
assertTrue("Request constructor is not public", Modifier.isPublic(constructors[0].getModifiers())); assertTrue("Request constructor is not public", Modifier.isPublic(constructors[0].getModifiers()));
} }
public void testClassVisibility() throws Exception { public void testClassVisibility() {
assertTrue("Request class is not public", Modifier.isPublic(Request.class.getModifiers())); assertTrue("Request class is not public", Modifier.isPublic(Request.class.getModifiers()));
} }
@ -146,7 +147,7 @@ public class RequestTests extends ESTestCase {
getAndExistsTest(Request::get, "GET"); getAndExistsTest(Request::get, "GET");
} }
public void testDelete() throws IOException { public void testDelete() {
String index = randomAlphaOfLengthBetween(3, 10); String index = randomAlphaOfLengthBetween(3, 10);
String type = randomAlphaOfLengthBetween(3, 10); String type = randomAlphaOfLengthBetween(3, 10);
String id = randomAlphaOfLengthBetween(3, 10); String id = randomAlphaOfLengthBetween(3, 10);
@ -283,7 +284,7 @@ public class RequestTests extends ESTestCase {
assertToXContentBody(createIndexRequest, request.getEntity()); assertToXContentBody(createIndexRequest, request.getEntity());
} }
public void testDeleteIndex() throws IOException { public void testDeleteIndex() {
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(); DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest();
int numIndices = randomIntBetween(0, 5); int numIndices = randomIntBetween(0, 5);
@ -307,6 +308,29 @@ public class RequestTests extends ESTestCase {
assertNull(request.getEntity()); assertNull(request.getEntity());
} }
public void testOpenIndex() {
OpenIndexRequest openIndexRequest = new OpenIndexRequest();
int numIndices = randomIntBetween(1, 5);
String[] indices = new String[numIndices];
for (int i = 0; i < numIndices; i++) {
indices[i] = "index-" + randomAlphaOfLengthBetween(2, 5);
}
openIndexRequest.indices(indices);
Map<String, String> expectedParams = new HashMap<>();
setRandomTimeout(openIndexRequest::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
setRandomMasterTimeout(openIndexRequest, expectedParams);
setRandomIndicesOptions(openIndexRequest::indicesOptions, openIndexRequest::indicesOptions, expectedParams);
setRandomWaitForActiveShards(openIndexRequest::waitForActiveShards, expectedParams);
Request request = Request.openIndex(openIndexRequest);
StringJoiner endpoint = new StringJoiner("/", "/", "").add(String.join(",", indices)).add("_open");
assertThat(endpoint.toString(), equalTo(request.getEndpoint()));
assertThat(expectedParams, equalTo(request.getParameters()));
assertThat(request.getMethod(), equalTo("POST"));
assertThat(request.getEntity(), nullValue());
}
public void testIndex() throws IOException { public void testIndex() throws IOException {
String index = randomAlphaOfLengthBetween(3, 10); String index = randomAlphaOfLengthBetween(3, 10);
String type = randomAlphaOfLengthBetween(3, 10); String type = randomAlphaOfLengthBetween(3, 10);

View File

@ -21,15 +21,34 @@ package org.elasticsearch.action.admin.indices.open;
import org.elasticsearch.Version; import org.elasticsearch.Version;
import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException; import java.io.IOException;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
/** /**
* A response for a open index action. * A response for a open index action.
*/ */
public class OpenIndexResponse extends AcknowledgedResponse { public class OpenIndexResponse extends AcknowledgedResponse implements ToXContentObject {
private static final String SHARDS_ACKNOWLEDGED = "shards_acknowledged";
private static final ParseField SHARDS_ACKNOWLEDGED_PARSER = new ParseField(SHARDS_ACKNOWLEDGED);
private static final ConstructingObjectParser<OpenIndexResponse, Void> PARSER = new ConstructingObjectParser<>("open_index", true,
args -> new OpenIndexResponse((boolean) args[0], (boolean) args[1]));
static {
declareAcknowledgedField(PARSER);
PARSER.declareField(constructorArg(), (parser, context) -> parser.booleanValue(), SHARDS_ACKNOWLEDGED_PARSER,
ObjectParser.ValueType.BOOLEAN);
}
private boolean shardsAcknowledged; private boolean shardsAcknowledged;
@ -68,4 +87,17 @@ public class OpenIndexResponse extends AcknowledgedResponse {
out.writeBoolean(shardsAcknowledged); out.writeBoolean(shardsAcknowledged);
} }
} }
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
addAcknowledgedField(builder);
builder.field(SHARDS_ACKNOWLEDGED, isShardsAcknowledged());
builder.endObject();
return builder;
}
public static OpenIndexResponse fromXContent(XContentParser parser) throws IOException {
return PARSER.apply(parser, null);
}
} }

View File

@ -0,0 +1,63 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.action.admin.indices.open;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import static org.elasticsearch.test.XContentTestUtils.insertRandomFields;
import static org.hamcrest.CoreMatchers.equalTo;
public class OpenIndexResponseTests extends ESTestCase {
public void testFromToXContent() throws IOException {
final OpenIndexResponse openIndexResponse = createTestItem();
boolean humanReadable = randomBoolean();
final XContentType xContentType = randomFrom(XContentType.values());
BytesReference originalBytes = toShuffledXContent(openIndexResponse, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
BytesReference mutated;
if (randomBoolean()) {
mutated = insertRandomFields(xContentType, originalBytes, null, random());
} else {
mutated = originalBytes;
}
OpenIndexResponse parsedOpenIndexResponse;
try (XContentParser parser = createParser(xContentType.xContent(), mutated)) {
parsedOpenIndexResponse = OpenIndexResponse.fromXContent(parser);
assertNull(parser.nextToken());
}
assertThat(parsedOpenIndexResponse.isShardsAcknowledged(), equalTo(openIndexResponse.isShardsAcknowledged()));
assertThat(parsedOpenIndexResponse.isAcknowledged(), equalTo(openIndexResponse.isAcknowledged()));
}
private static OpenIndexResponse createTestItem() {
boolean acknowledged = randomBoolean();
boolean shardsAcked = acknowledged && randomBoolean();
return new OpenIndexResponse(acknowledged, shardsAcked);
}
}