Explorar o código

Add support for indices exists to REST high level client (#27384)

Relates to #27205
Haris Osmanagić %!s(int64=7) %!d(string=hai) anos
pai
achega
897ef458f3

+ 35 - 0
client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java

@@ -30,6 +30,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
@@ -38,6 +39,7 @@ import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
 import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
 
 import java.io.IOException;
+import java.util.Collections;
 
 import static java.util.Collections.emptySet;
 
@@ -211,6 +213,39 @@ public final class IndicesClient {
                 listener, emptySet(), headers);
     }
 
+    /**
+     * Checks if the index (indices) exists or not.
+     * <p>
+     * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html">
+     * Indices Exists API on elastic.co</a>
+     */
+    public boolean exists(GetIndexRequest request, Header... headers) throws IOException {
+        return restHighLevelClient.performRequest(
+            request,
+            Request::indicesExist,
+            RestHighLevelClient::convertExistsResponse,
+            Collections.emptySet(),
+            headers
+        );
+    }
+
+    /**
+     * Asynchronously checks if the index (indices) exists or not.
+     * <p>
+     * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-exists.html">
+     * Indices Exists API on elastic.co</a>
+     */
+    public void existsAsync(GetIndexRequest request, ActionListener<Boolean> listener, Header... headers) {
+        restHighLevelClient.performRequestAsync(
+            request,
+            Request::indicesExist,
+            RestHighLevelClient::convertExistsResponse,
+            listener,
+            Collections.emptySet(),
+            headers
+        );
+    }
+
     /**
      * Shrinks an index using the Shrink Index API
      * <p>

+ 36 - 1
client/rest-high-level/src/main/java/org/elasticsearch/client/Request.java

@@ -34,6 +34,7 @@ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
@@ -582,6 +583,17 @@ public final class Request {
         return ContentType.create(xContentType.mediaTypeWithoutParameters(), (Charset) null);
     }
 
+    static Request indicesExist(GetIndexRequest request) {
+        String endpoint = endpoint(request.indices(), Strings.EMPTY_ARRAY, "");
+        Params params = Params.builder();
+        params.withLocal(request.local());
+        params.withHuman(request.humanReadable());
+        params.withIndicesOptions(request.indicesOptions());
+        params.withFlatSettings(request.flatSettings());
+        params.withIncludeDefaults(request.includeDefaults());
+        return new Request(HttpHead.METHOD_NAME, endpoint, params.getParams(), null);
+    }
+
     /**
      * Utility class to build request's parameters map and centralize all parameter names.
      */
@@ -729,8 +741,31 @@ public final class Request {
             return this;
         }
 
+        Params withHuman(boolean human) {
+            if (human) {
+                putParam("human", Boolean.toString(human));
+            }
+            return this;
+        }
+
         Params withLocal(boolean local) {
-            putParam("local", Boolean.toString(local));
+            if (local) {
+                putParam("local", Boolean.toString(local));
+            }
+            return this;
+        }
+
+        Params withFlatSettings(boolean flatSettings) {
+            if (flatSettings) {
+                return putParam("flat_settings", Boolean.TRUE.toString());
+            }
+            return this;
+        }
+
+        Params withIncludeDefaults(boolean includeDefaults) {
+            if (includeDefaults) {
+                return putParam("include_defaults", Boolean.TRUE.toString());
+            }
             return this;
         }
 

+ 53 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

@@ -34,6 +34,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
@@ -58,6 +59,58 @@ import static org.hamcrest.Matchers.not;
 
 public class IndicesClientIT extends ESRestHighLevelClientTestCase {
 
+    public void testIndicesExists() throws IOException {
+        // Index present
+        {
+            String indexName = "test_index_exists_index_present";
+            createIndex(indexName, Settings.EMPTY);
+
+            GetIndexRequest request = new GetIndexRequest();
+            request.indices(indexName);
+
+            boolean response = execute(
+                request,
+                highLevelClient().indices()::exists,
+                highLevelClient().indices()::existsAsync
+            );
+            assertTrue(response);
+        }
+
+        // Index doesn't exist
+        {
+            String indexName = "non_existent_index";
+
+            GetIndexRequest request = new GetIndexRequest();
+            request.indices(indexName);
+
+            boolean response = execute(
+                request,
+                highLevelClient().indices()::exists,
+                highLevelClient().indices()::existsAsync
+            );
+            assertFalse(response);
+        }
+
+        // One index exists, one doesn't
+        {
+            String existingIndex = "apples";
+            createIndex(existingIndex, Settings.EMPTY);
+
+            String nonExistentIndex = "oranges";
+
+            GetIndexRequest request = new GetIndexRequest();
+            request.indices(existingIndex, nonExistentIndex);
+
+            boolean response = execute(
+                request,
+                highLevelClient().indices()::exists,
+                highLevelClient().indices()::existsAsync
+            );
+            assertFalse(response);
+        }
+
+    }
+
     @SuppressWarnings({"unchecked", "rawtypes"})
     public void testCreateIndex() throws IOException {
         {

+ 63 - 6
client/rest-high-level/src/test/java/org/elasticsearch/client/RequestTests.java

@@ -36,6 +36,7 @@ import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
 import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
 import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
@@ -55,6 +56,7 @@ import org.elasticsearch.action.support.ActiveShardCount;
 import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.WriteRequest;
 import org.elasticsearch.action.support.master.AcknowledgedRequest;
+import org.elasticsearch.action.support.master.MasterNodeReadRequest;
 import org.elasticsearch.action.support.master.MasterNodeRequest;
 import org.elasticsearch.action.support.replication.ReplicationRequest;
 import org.elasticsearch.action.update.UpdateRequest;
@@ -262,6 +264,26 @@ public class RequestTests extends ESTestCase {
         getAndExistsTest(Request::exists, HttpHead.METHOD_NAME);
     }
 
+    public void testIndicesExist() {
+        String[] indices = randomIndicesNames(1, 10);
+
+        GetIndexRequest getIndexRequest = new GetIndexRequest().indices(indices);
+
+        Map<String, String> expectedParams = new HashMap<>();
+        setRandomIndicesOptions(getIndexRequest::indicesOptions, getIndexRequest::indicesOptions, expectedParams);
+        setRandomLocal(getIndexRequest, expectedParams);
+        setRandomFlatSettings(getIndexRequest, expectedParams);
+        setRandomHumanReadable(getIndexRequest, expectedParams);
+        setRandomIncludeDefaults(getIndexRequest, expectedParams);
+
+        final Request request = Request.indicesExist(getIndexRequest);
+
+        assertEquals(HttpHead.METHOD_NAME, request.getMethod());
+        assertEquals("/" + String.join(",", indices), request.getEndpoint());
+        assertThat(expectedParams, equalTo(request.getParameters()));
+        assertNull(request.getEntity());
+    }
+
     private static void getAndExistsTest(Function<GetRequest, Request> requestConverter, String method) {
         String index = randomAlphaOfLengthBetween(3, 10);
         String type = randomAlphaOfLengthBetween(3, 10);
@@ -1008,12 +1030,7 @@ public class RequestTests extends ESTestCase {
         String[] aliases = randomIndicesNames(indices.length == 0 ? 1 : 0, 5);
         getAliasesRequest.aliases(aliases);
         Map<String, String> expectedParams = new HashMap<>();
-        if (randomBoolean()) {
-            boolean local = randomBoolean();
-            getAliasesRequest.local(local);
-        }
-        expectedParams.put("local", Boolean.toString(getAliasesRequest.local()));
-
+        setRandomLocal(getAliasesRequest, expectedParams);
         setRandomIndicesOptions(getAliasesRequest::indicesOptions, getAliasesRequest::indicesOptions, expectedParams);
 
         Request request = Request.existsAlias(getAliasesRequest);
@@ -1252,6 +1269,46 @@ public class RequestTests extends ESTestCase {
         }
     }
 
+    private static void setRandomIncludeDefaults(GetIndexRequest request, Map<String, String> expectedParams) {
+        if (randomBoolean()) {
+            boolean includeDefaults = randomBoolean();
+            request.includeDefaults(includeDefaults);
+            if (includeDefaults) {
+                expectedParams.put("include_defaults", String.valueOf(includeDefaults));
+            }
+        }
+    }
+
+    private static void setRandomHumanReadable(GetIndexRequest request, Map<String, String> expectedParams) {
+        if (randomBoolean()) {
+            boolean humanReadable = randomBoolean();
+            request.humanReadable(humanReadable);
+            if (humanReadable) {
+                expectedParams.put("human", String.valueOf(humanReadable));
+            }
+        }
+    }
+
+    private static void setRandomFlatSettings(GetIndexRequest request, Map<String, String> expectedParams) {
+        if (randomBoolean()) {
+            boolean flatSettings = randomBoolean();
+            request.flatSettings(flatSettings);
+            if (flatSettings) {
+                expectedParams.put("flat_settings", String.valueOf(flatSettings));
+            }
+        }
+    }
+
+    private static void setRandomLocal(MasterNodeReadRequest<?> request, Map<String, String> expectedParams) {
+        if (randomBoolean()) {
+            boolean local = randomBoolean();
+            request.local(local);
+            if (local) {
+                expectedParams.put("local", String.valueOf(local));
+            }
+        }
+    }
+
     private static void setRandomTimeout(Consumer<String> setter, TimeValue defaultTimeout, Map<String, String> expectedParams) {
         if (randomBoolean()) {
             String timeout = randomTimeValue();

+ 65 - 0
client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java

@@ -19,6 +19,7 @@
 
 package org.elasticsearch.client.documentation;
 
+import org.apache.http.Header;
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.ActionListener;
 import org.elasticsearch.action.LatchedActionListener;
@@ -33,6 +34,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
 import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
 import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
+import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
 import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse;
 import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
@@ -74,6 +76,69 @@ import java.util.concurrent.TimeUnit;
  */
 public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase {
 
+    public void testIndicesExist() throws IOException {
+        RestHighLevelClient client = highLevelClient();
+
+        {
+            CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"));
+            assertTrue(createIndexResponse.isAcknowledged());
+        }
+
+        {
+            // tag::indices-exists-request
+            GetIndexRequest request = new GetIndexRequest();
+            request.indices("twitter"); // <1>
+            // end::indices-exists-request
+
+            IndicesOptions indicesOptions = IndicesOptions.strictExpand();
+            // tag::indices-exists-request-optionals
+            request.local(false); // <1>
+            request.humanReadable(true); // <2>
+            request.includeDefaults(false); // <3>
+            request.flatSettings(false); // <4>
+            request.indicesOptions(indicesOptions); // <5>
+            // end::indices-exists-request-optionals
+
+            Header[] headers = new Header[0];
+            // tag::indices-exists-response
+            boolean exists = client.indices().exists(request, headers);
+            // end::indices-exists-response
+            assertTrue(exists);
+        }
+    }
+
+    public void testIndicesExistAsync() throws IOException {
+        RestHighLevelClient client = highLevelClient();
+
+        {
+            CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("twitter"));
+            assertTrue(createIndexResponse.isAcknowledged());
+        }
+
+        {
+            GetIndexRequest request = new GetIndexRequest();
+            request.indices("twitter");
+            Header[] headers = new Header[0];
+
+            // tag::indices-exists-async
+            client.indices().existsAsync(
+                request,
+                new ActionListener<Boolean>() {
+                    @Override
+                    public void onResponse(Boolean exists) {
+                        // <1>
+                    }
+
+                    @Override
+                    public void onFailure(Exception e) {
+                        // <2>
+                    }
+                },
+                headers
+            );
+            // end::indices-exists-async
+        }
+    }
     public void testDeleteIndex() throws IOException {
         RestHighLevelClient client = highLevelClient();
 

+ 2 - 0
docs/java-rest/high-level/apis/index.asciidoc

@@ -1,5 +1,7 @@
 include::create_index.asciidoc[]
 
+include::indices_exists.asciidoc[]
+
 include::delete_index.asciidoc[]
 
 include::open_index.asciidoc[]

+ 57 - 0
docs/java-rest/high-level/apis/indices_exists.asciidoc

@@ -0,0 +1,57 @@
+[[java-rest-high-indices-exists]]
+=== Indices Exists API
+
+[[java-rest-high-indices-exists-request]]
+==== Indices Exists Request
+
+The high-level REST client uses a `GetIndexRequest` for Indices Exists API. The index name (or indices' names) are required.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-request]
+--------------------------------------------------
+<1> Index
+
+[[java-rest-high-indices-exists-optional-args]]
+==== Optional arguments
+Indices Exists API also accepts following optional arguments, through a `GetIndexRequest`:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-request-optionals]
+--------------------------------------------------
+<1> Whether to return local information or retrieve the state from master node
+<2> Return result in a format suitable for humans
+<3> Whether to return all default setting for each of the indices
+<4> Return settings in flat format
+<5> Controls how unavailable indices are resolved and how wildcard expressions are expanded
+
+[[java-rest-high-indices-sync]]
+==== Synchronous Execution
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-response]
+--------------------------------------------------
+
+[[java-rest-high-indices-async]]
+==== Asynchronous Execution
+As is the case with many other APIs, the Indices Exists API has an asynchronous variant in the
+Java High Level REST Client.
+The asynchronous variant returns void and accept an extra `ActionListener` as an argument.
+The provided listener will be notified upon request completion or failure.
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-async]
+--------------------------------------------------
+<1> Called when the execution is successfully completed. The response is provided as an argument
+<2> Called in case of failure. The raised exception is provided as an argument
+
+[[java-rest-high-indices-exists-response]]
+==== Response
+The response is a `boolean` value, indicating whether the index (or indices) exist:
+
+["source","java",subs="attributes,callouts,macros"]
+--------------------------------------------------
+include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[indices-exists-response]
+--------------------------------------------------

+ 1 - 0
docs/java-rest/high-level/supported-apis.asciidoc

@@ -6,6 +6,7 @@ The Java High Level REST Client supports the following APIs:
 Indices APIs::
 * <<java-rest-high-create-index>>
 * <<java-rest-high-delete-index>>
+* <<java-rest-high-indices-exists>>
 * <<java-rest-high-open-index>>
 * <<java-rest-high-close-index>>
 * <<java-rest-high-put-mapping>>

+ 1 - 1
server/src/main/java/org/elasticsearch/action/admin/indices/exists/indices/IndicesExistsResponse.java

@@ -51,4 +51,4 @@ public class IndicesExistsResponse extends ActionResponse {
         super.writeTo(out);
         out.writeBoolean(exists);
     }
-}
+}

+ 39 - 1
server/src/main/java/org/elasticsearch/action/admin/indices/get/GetIndexRequest.java

@@ -33,7 +33,6 @@ import java.util.List;
  * A request to delete an index. Best created with {@link org.elasticsearch.client.Requests#deleteIndexRequest(String)}.
  */
 public class GetIndexRequest extends ClusterInfoRequest<GetIndexRequest> {
-
     public enum Feature {
         ALIASES((byte) 0, "_aliases", "_alias"),
         MAPPINGS((byte) 1, "_mappings", "_mapping"),
@@ -99,6 +98,8 @@ public class GetIndexRequest extends ClusterInfoRequest<GetIndexRequest> {
     private static final Feature[] DEFAULT_FEATURES = new Feature[] { Feature.ALIASES, Feature.MAPPINGS, Feature.SETTINGS };
     private Feature[] features = DEFAULT_FEATURES;
     private boolean humanReadable = false;
+    private transient boolean flatSettings = false;
+    private transient boolean includeDefaults = false;
 
     public GetIndexRequest() {
 
@@ -149,6 +150,43 @@ public class GetIndexRequest extends ClusterInfoRequest<GetIndexRequest> {
         return humanReadable;
     }
 
+    /**
+     * Sets the value of "flat_settings".
+     * @param flatSettings value of "flat_settings" flag to be set
+     * @return this request
+     */
+    public GetIndexRequest flatSettings(boolean flatSettings) {
+        this.flatSettings = flatSettings;
+        return this;
+    }
+
+    /**
+     * Return settings in flat format.
+     * @return <code>true</code> if settings need to be returned in flat format; <code>false</code> otherwise.
+     */
+    public boolean flatSettings() {
+        return flatSettings;
+    }
+
+    /**
+     * Sets the value of "include_defaults".
+     * @param includeDefaults value of "include_defaults" to be set.
+     * @return this request
+     */
+    public GetIndexRequest includeDefaults(boolean includeDefaults) {
+        this.includeDefaults = includeDefaults;
+        return this;
+    }
+
+    /**
+     * Whether to return all default settings for each of the indices.
+     * @return <code>true</code> if defaults settings for each of the indices need to returned;
+     * <code>false</code> otherwise.
+     */
+    public boolean includeDefaults() {
+        return includeDefaults;
+    }
+
     @Override
     public void readFrom(StreamInput in) throws IOException {
         throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");

+ 5 - 0
server/src/main/java/org/elasticsearch/action/support/master/MasterNodeReadRequest.java

@@ -51,6 +51,11 @@ public abstract class MasterNodeReadRequest<Request extends MasterNodeReadReques
         return (Request) this;
     }
 
+    /**
+     * Return local information, do not retrieve the state from master node (default: false).
+     * @return <code>true</code> if local information is to be returned;
+     * <code>false</code> if information is to be retrieved from master node (default).
+     */
     public final boolean local() {
         return local;
     }