Add Get Aliases API to the high-level REST client (#28799)
Given the weirdness of the response returned by the get alias API, we went for a client specific response, which allows us to hold the error message, exception and status returned as part of the response together with aliases. See #30536 . Relates to #27205
This commit is contained in:
parent
a178290b60
commit
7d7ead95b2
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* 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.client;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.common.xcontent.StatusToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser.Token;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||
|
||||
/**
|
||||
* Response obtained from the get aliases API.
|
||||
* The format is pretty horrible as it holds aliases, but at the same time errors can come back through the status and error fields.
|
||||
* Such errors are mostly 404 - NOT FOUND for aliases that were specified but not found. In such case the client won't throw exception
|
||||
* so it allows to retrieve the returned aliases, while at the same time checking if errors were returned.
|
||||
* There's also the case where an exception is returned, like for instance an {@link org.elasticsearch.index.IndexNotFoundException}.
|
||||
* We would usually throw such exception, but we configure the client to not throw for 404 to support the case above, hence we also not
|
||||
* throw in case an index is not found, although it is a hard error that doesn't come back with aliases.
|
||||
*/
|
||||
public class GetAliasesResponse extends ActionResponse implements StatusToXContentObject {
|
||||
|
||||
private final RestStatus status;
|
||||
private final String error;
|
||||
private final ElasticsearchException exception;
|
||||
|
||||
private final Map<String, Set<AliasMetaData>> aliases;
|
||||
|
||||
GetAliasesResponse(RestStatus status, String error, Map<String, Set<AliasMetaData>> aliases) {
|
||||
this.status = status;
|
||||
this.error = error;
|
||||
this.aliases = aliases;
|
||||
this.exception = null;
|
||||
}
|
||||
|
||||
private GetAliasesResponse(RestStatus status, ElasticsearchException exception) {
|
||||
this.status = status;
|
||||
this.error = null;
|
||||
this.aliases = Collections.emptyMap();
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RestStatus status() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the possibly returned error, null otherwise
|
||||
*/
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the exception that may have been returned
|
||||
*/
|
||||
public ElasticsearchException getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the requested aliases
|
||||
*/
|
||||
public Map<String, Set<AliasMetaData>> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
{
|
||||
if (status != RestStatus.OK) {
|
||||
builder.field("error", error);
|
||||
builder.field("status", status.getStatus());
|
||||
}
|
||||
|
||||
for (Map.Entry<String, Set<AliasMetaData>> entry : aliases.entrySet()) {
|
||||
builder.startObject(entry.getKey());
|
||||
{
|
||||
builder.startObject("aliases");
|
||||
{
|
||||
for (final AliasMetaData alias : entry.getValue()) {
|
||||
AliasMetaData.Builder.toXContent(alias, builder, ToXContent.EMPTY_PARAMS);
|
||||
}
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the get aliases response
|
||||
*/
|
||||
public static GetAliasesResponse fromXContent(XContentParser parser) throws IOException {
|
||||
if (parser.currentToken() == null) {
|
||||
parser.nextToken();
|
||||
}
|
||||
ensureExpectedToken(Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation);
|
||||
Map<String, Set<AliasMetaData>> aliases = new HashMap<>();
|
||||
|
||||
String currentFieldName;
|
||||
Token token;
|
||||
String error = null;
|
||||
ElasticsearchException exception = null;
|
||||
RestStatus status = RestStatus.OK;
|
||||
|
||||
while (parser.nextToken() != Token.END_OBJECT) {
|
||||
if (parser.currentToken() == Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
|
||||
if ("status".equals(currentFieldName)) {
|
||||
if ((token = parser.nextToken()) != Token.FIELD_NAME) {
|
||||
ensureExpectedToken(Token.VALUE_NUMBER, token, parser::getTokenLocation);
|
||||
status = RestStatus.fromCode(parser.intValue());
|
||||
}
|
||||
} else if ("error".equals(currentFieldName)) {
|
||||
token = parser.nextToken();
|
||||
if (token == Token.VALUE_STRING) {
|
||||
error = parser.text();
|
||||
} else if (token == Token.START_OBJECT) {
|
||||
parser.nextToken();
|
||||
exception = ElasticsearchException.innerFromXContent(parser, true);
|
||||
} else if (token == Token.START_ARRAY) {
|
||||
parser.skipChildren();
|
||||
}
|
||||
} else {
|
||||
String indexName = parser.currentName();
|
||||
if (parser.nextToken() == Token.START_OBJECT) {
|
||||
Set<AliasMetaData> parseInside = parseAliases(parser);
|
||||
aliases.put(indexName, parseInside);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (exception != null) {
|
||||
assert error == null;
|
||||
assert aliases.isEmpty();
|
||||
return new GetAliasesResponse(status, exception);
|
||||
}
|
||||
return new GetAliasesResponse(status, error, aliases);
|
||||
}
|
||||
|
||||
private static Set<AliasMetaData> parseAliases(XContentParser parser) throws IOException {
|
||||
Set<AliasMetaData> aliases = new HashSet<>();
|
||||
Token token;
|
||||
String currentFieldName = null;
|
||||
while ((token = parser.nextToken()) != Token.END_OBJECT) {
|
||||
if (token == Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
} else if (token == Token.START_OBJECT) {
|
||||
if ("aliases".equals(currentFieldName)) {
|
||||
while (parser.nextToken() != Token.END_OBJECT) {
|
||||
AliasMetaData fromXContent = AliasMetaData.Builder.fromXContent(parser);
|
||||
aliases.add(fromXContent);
|
||||
}
|
||||
} else {
|
||||
parser.skipChildren();
|
||||
}
|
||||
} else if (token == Token.START_ARRAY) {
|
||||
parser.skipChildren();
|
||||
}
|
||||
}
|
||||
return aliases;
|
||||
}
|
||||
}
|
|
@ -58,11 +58,13 @@ import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequ
|
|||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
||||
import static java.util.Collections.emptySet;
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
/**
|
||||
* A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the Indices API.
|
||||
|
@ -978,6 +980,33 @@ public final class IndicesClient {
|
|||
listener, emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets one or more aliases using the Get Index Aliases API.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html"> Indices Aliases API on
|
||||
* elastic.co</a>
|
||||
* @param getAliasesRequest the request
|
||||
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||
* @return the response
|
||||
* @throws IOException in case there is a problem sending the request or parsing back the response
|
||||
*/
|
||||
public GetAliasesResponse getAlias(GetAliasesRequest getAliasesRequest, RequestOptions options) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(getAliasesRequest, RequestConverters::getAlias, options,
|
||||
GetAliasesResponse::fromXContent, singleton(RestStatus.NOT_FOUND.getStatus()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously gets one or more aliases using the Get Index Aliases API.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-aliases.html"> Indices Aliases API on
|
||||
* elastic.co</a>
|
||||
* @param getAliasesRequest the request
|
||||
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
|
||||
* @param listener the listener to be notified upon request completion
|
||||
*/
|
||||
public void getAliasAsync(GetAliasesRequest getAliasesRequest, RequestOptions options, ActionListener<GetAliasesResponse> listener) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(getAliasesRequest, RequestConverters::getAlias, options,
|
||||
GetAliasesResponse::fromXContent, listener, singleton(RestStatus.NOT_FOUND.getStatus()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates specific index level settings using the Update Indices Settings API.
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html"> Update Indices Settings
|
||||
|
|
|
@ -831,6 +831,17 @@ final class RequestConverters {
|
|||
return request;
|
||||
}
|
||||
|
||||
static Request getAlias(GetAliasesRequest getAliasesRequest) {
|
||||
String[] indices = getAliasesRequest.indices() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.indices();
|
||||
String[] aliases = getAliasesRequest.aliases() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.aliases();
|
||||
String endpoint = endpoint(indices, "_alias", aliases);
|
||||
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
|
||||
Params params = new Params(request);
|
||||
params.withIndicesOptions(getAliasesRequest.indicesOptions());
|
||||
params.withLocal(getAliasesRequest.local());
|
||||
return request;
|
||||
}
|
||||
|
||||
static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) throws IOException {
|
||||
String[] names = getIndexTemplatesRequest.names();
|
||||
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addCommaSeparatedPathParts(names).build();
|
||||
|
|
|
@ -1021,10 +1021,10 @@ public class RestHighLevelClient implements Closeable {
|
|||
try {
|
||||
return responseConverter.apply(e.getResponse());
|
||||
} catch (Exception innerException) {
|
||||
//the exception is ignored as we now try to parse the response as an error.
|
||||
//this covers cases like get where 404 can either be a valid document not found response,
|
||||
//or an error for which parsing is completely different. We try to consider the 404 response as a valid one
|
||||
//first. If parsing of the response breaks, we fall back to parsing it as an error.
|
||||
// the exception is ignored as we now try to parse the response as an error.
|
||||
// this covers cases like get where 404 can either be a valid document not found response,
|
||||
// or an error for which parsing is completely different. We try to consider the 404 response as a valid one
|
||||
// first. If parsing of the response breaks, we fall back to parsing it as an error.
|
||||
throw parseResponseException(e);
|
||||
}
|
||||
}
|
||||
|
@ -1109,10 +1109,10 @@ public class RestHighLevelClient implements Closeable {
|
|||
try {
|
||||
actionListener.onResponse(responseConverter.apply(response));
|
||||
} catch (Exception innerException) {
|
||||
//the exception is ignored as we now try to parse the response as an error.
|
||||
//this covers cases like get where 404 can either be a valid document not found response,
|
||||
//or an error for which parsing is completely different. We try to consider the 404 response as a valid one
|
||||
//first. If parsing of the response breaks, we fall back to parsing it as an error.
|
||||
// the exception is ignored as we now try to parse the response as an error.
|
||||
// this covers cases like get where 404 can either be a valid document not found response,
|
||||
// or an error for which parsing is completely different. We try to consider the 404 response as a valid one
|
||||
// first. If parsing of the response breaks, we fall back to parsing it as an error.
|
||||
actionListener.onFailure(parseResponseException(responseException));
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* 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.client;
|
||||
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.json.JsonXContent;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.AbstractXContentTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
|
||||
public class GetAliasesResponseTests extends AbstractXContentTestCase<GetAliasesResponse> {
|
||||
|
||||
@Override
|
||||
protected GetAliasesResponse createTestInstance() {
|
||||
RestStatus status = randomFrom(RestStatus.OK, RestStatus.NOT_FOUND);
|
||||
String errorMessage = RestStatus.OK == status ? null : randomAlphaOfLengthBetween(5, 10);
|
||||
return new GetAliasesResponse(status, errorMessage, createIndicesAliasesMap(0, 5));
|
||||
}
|
||||
|
||||
private static Map<String, Set<AliasMetaData>> createIndicesAliasesMap(int min, int max) {
|
||||
Map<String, Set<AliasMetaData>> map = new HashMap<>();
|
||||
int indicesNum = randomIntBetween(min, max);
|
||||
for (int i = 0; i < indicesNum; i++) {
|
||||
String index = randomAlphaOfLength(5);
|
||||
Set<AliasMetaData> aliasMetaData = new HashSet<>();
|
||||
int aliasesNum = randomIntBetween(0, 3);
|
||||
for (int alias = 0; alias < aliasesNum; alias++) {
|
||||
aliasMetaData.add(createAliasMetaData());
|
||||
}
|
||||
map.put(index, aliasMetaData);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static AliasMetaData createAliasMetaData() {
|
||||
AliasMetaData.Builder builder = AliasMetaData.builder(randomAlphaOfLengthBetween(3, 10));
|
||||
if (randomBoolean()) {
|
||||
builder.routing(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
builder.searchRouting(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
builder.indexRouting(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
builder.filter("{\"term\":{\"year\":2016}}");
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetAliasesResponse doParseInstance(XContentParser parser) throws IOException {
|
||||
return GetAliasesResponse.fromXContent(parser);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Predicate<String> getRandomFieldsExcludeFilter() {
|
||||
return p -> p.equals("") // do not add elements at the top-level as any element at this level is parsed as a new index
|
||||
|| p.endsWith(".aliases") // do not add new alias
|
||||
|| p.contains(".filter"); // do not insert random data into AliasMetaData#filter
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsUnknownFields() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertEqualInstances(GetAliasesResponse expectedInstance, GetAliasesResponse newInstance) {
|
||||
assertEquals(expectedInstance.getAliases(), newInstance.getAliases());
|
||||
assertEquals(expectedInstance.status(), newInstance.status());
|
||||
assertEquals(expectedInstance.getError(), newInstance.getError());
|
||||
assertNull(expectedInstance.getException());
|
||||
assertNull(newInstance.getException());
|
||||
}
|
||||
|
||||
public void testFromXContentWithElasticsearchException() throws IOException {
|
||||
String xContent =
|
||||
"{" +
|
||||
" \"error\": {" +
|
||||
" \"root_cause\": [" +
|
||||
" {" +
|
||||
" \"type\": \"index_not_found_exception\"," +
|
||||
" \"reason\": \"no such index\"," +
|
||||
" \"resource.type\": \"index_or_alias\"," +
|
||||
" \"resource.id\": \"index\"," +
|
||||
" \"index_uuid\": \"_na_\"," +
|
||||
" \"index\": \"index\"" +
|
||||
" }" +
|
||||
" ]," +
|
||||
" \"type\": \"index_not_found_exception\"," +
|
||||
" \"reason\": \"no such index\"," +
|
||||
" \"resource.type\": \"index_or_alias\"," +
|
||||
" \"resource.id\": \"index\"," +
|
||||
" \"index_uuid\": \"_na_\"," +
|
||||
" \"index\": \"index\"" +
|
||||
" }," +
|
||||
" \"status\": 404" +
|
||||
"}";
|
||||
|
||||
try (XContentParser parser = createParser(JsonXContent.jsonXContent, xContent)) {
|
||||
GetAliasesResponse getAliasesResponse = GetAliasesResponse.fromXContent(parser);
|
||||
assertThat(getAliasesResponse.getError(), nullValue());
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(getAliasesResponse.getException().getMessage(),
|
||||
equalTo("Elasticsearch exception [type=index_not_found_exception, reason=no such index]"));
|
||||
}
|
||||
}
|
||||
|
||||
public void testFromXContentWithNoAliasFound() throws IOException {
|
||||
String xContent =
|
||||
"{" +
|
||||
" \"error\": \"alias [aa] missing\"," +
|
||||
" \"status\": 404" +
|
||||
"}";
|
||||
try (XContentParser parser = createParser(JsonXContent.jsonXContent, xContent)) {
|
||||
GetAliasesResponse getAliasesResponse = GetAliasesResponse.fromXContent(parser);
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(getAliasesResponse.getError(), equalTo("alias [aa] missing"));
|
||||
assertThat(getAliasesResponse.getException(), nullValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void testFromXContentWithMissingAndFoundAlias() throws IOException {
|
||||
String xContent =
|
||||
"{" +
|
||||
" \"error\": \"alias [something] missing\"," +
|
||||
" \"status\": 404," +
|
||||
" \"index\": {" +
|
||||
" \"aliases\": {" +
|
||||
" \"alias\": {}" +
|
||||
" }" +
|
||||
" }" +
|
||||
"}";
|
||||
final String index = "index";
|
||||
try (XContentParser parser = createParser(JsonXContent.jsonXContent, xContent)) {
|
||||
GetAliasesResponse response = GetAliasesResponse.fromXContent(parser);
|
||||
assertThat(response.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(response.getError(), equalTo("alias [something] missing"));
|
||||
assertThat(response.getAliases().size(), equalTo(1));
|
||||
assertThat(response.getAliases().get(index).size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData = response.getAliases().get(index).iterator().next();
|
||||
assertThat(aliasMetaData.alias(), equalTo("alias"));
|
||||
assertThat(response.getException(), nullValue());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,10 +52,10 @@ import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
|||
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
||||
|
@ -67,6 +67,7 @@ import org.elasticsearch.action.index.IndexRequest;
|
|||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||
import org.elasticsearch.common.ValidationException;
|
||||
|
@ -98,6 +99,8 @@ import static org.hamcrest.Matchers.equalTo;
|
|||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
public class IndicesClientIT extends ESRestHighLevelClientTestCase {
|
||||
|
@ -320,28 +323,27 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals(0, getSettingsResponse.getIndexToSettings().get("get_settings_index").size());
|
||||
assertEquals(1, getSettingsResponse.getIndexToDefaultSettings().get("get_settings_index").size());
|
||||
}
|
||||
|
||||
public void testPutMapping() throws IOException {
|
||||
{
|
||||
// Add mappings to index
|
||||
String indexName = "mapping_index";
|
||||
createIndex(indexName, Settings.EMPTY);
|
||||
// Add mappings to index
|
||||
String indexName = "mapping_index";
|
||||
createIndex(indexName, Settings.EMPTY);
|
||||
|
||||
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
|
||||
putMappingRequest.type("type_name");
|
||||
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
|
||||
mappingBuilder.startObject().startObject("properties").startObject("field");
|
||||
mappingBuilder.field("type", "text");
|
||||
mappingBuilder.endObject().endObject().endObject();
|
||||
putMappingRequest.source(mappingBuilder);
|
||||
PutMappingRequest putMappingRequest = new PutMappingRequest(indexName);
|
||||
putMappingRequest.type("type_name");
|
||||
XContentBuilder mappingBuilder = JsonXContent.contentBuilder();
|
||||
mappingBuilder.startObject().startObject("properties").startObject("field");
|
||||
mappingBuilder.field("type", "text");
|
||||
mappingBuilder.endObject().endObject().endObject();
|
||||
putMappingRequest.source(mappingBuilder);
|
||||
|
||||
PutMappingResponse putMappingResponse =
|
||||
execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync,
|
||||
highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
|
||||
assertTrue(putMappingResponse.isAcknowledged());
|
||||
PutMappingResponse putMappingResponse =
|
||||
execute(putMappingRequest, highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync,
|
||||
highLevelClient().indices()::putMapping, highLevelClient().indices()::putMappingAsync);
|
||||
assertTrue(putMappingResponse.isAcknowledged());
|
||||
|
||||
Map<String, Object> getIndexResponse = getAsMap(indexName);
|
||||
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
|
||||
}
|
||||
Map<String, Object> getIndexResponse = getAsMap(indexName);
|
||||
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
|
||||
}
|
||||
|
||||
public void testGetMapping() throws IOException {
|
||||
|
@ -853,6 +855,197 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public void testGetAlias() throws IOException {
|
||||
{
|
||||
createIndex("index1", Settings.EMPTY);
|
||||
client().performRequest(HttpPut.METHOD_NAME, "/index1/_alias/alias1");
|
||||
|
||||
createIndex("index2", Settings.EMPTY);
|
||||
client().performRequest(HttpPut.METHOD_NAME, "/index2/_alias/alias2");
|
||||
|
||||
createIndex("index3", Settings.EMPTY);
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().aliases("alias1");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(1));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData, notNullValue());
|
||||
assertThat(aliasMetaData.alias(), equalTo("alias1"));
|
||||
assertThat(aliasMetaData.getFilter(), nullValue());
|
||||
assertThat(aliasMetaData.getIndexRouting(), nullValue());
|
||||
assertThat(aliasMetaData.getSearchRouting(), nullValue());
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().aliases("alias*");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(2));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData1 = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData1, notNullValue());
|
||||
assertThat(aliasMetaData1.alias(), equalTo("alias1"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index2").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData2 = getAliasesResponse.getAliases().get("index2").iterator().next();
|
||||
assertThat(aliasMetaData2, notNullValue());
|
||||
assertThat(aliasMetaData2.alias(), equalTo("alias2"));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().aliases("_all");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(2));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData1 = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData1, notNullValue());
|
||||
assertThat(aliasMetaData1.alias(), equalTo("alias1"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index2").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData2 = getAliasesResponse.getAliases().get("index2").iterator().next();
|
||||
assertThat(aliasMetaData2, notNullValue());
|
||||
assertThat(aliasMetaData2.alias(), equalTo("alias2"));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().aliases("*");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(2));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData1 = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData1, notNullValue());
|
||||
assertThat(aliasMetaData1.alias(), equalTo("alias1"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index2").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData2 = getAliasesResponse.getAliases().get("index2").iterator().next();
|
||||
assertThat(aliasMetaData2, notNullValue());
|
||||
assertThat(aliasMetaData2.alias(), equalTo("alias2"));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices("_all");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(3));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData1 = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData1, notNullValue());
|
||||
assertThat(aliasMetaData1.alias(), equalTo("alias1"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index2").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData2 = getAliasesResponse.getAliases().get("index2").iterator().next();
|
||||
assertThat(aliasMetaData2, notNullValue());
|
||||
assertThat(aliasMetaData2.alias(), equalTo("alias2"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index3").size(), equalTo(0));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices("ind*");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(3));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData1 = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData1, notNullValue());
|
||||
assertThat(aliasMetaData1.alias(), equalTo("alias1"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index2").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData2 = getAliasesResponse.getAliases().get("index2").iterator().next();
|
||||
assertThat(aliasMetaData2, notNullValue());
|
||||
assertThat(aliasMetaData2.alias(), equalTo("alias2"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index3").size(), equalTo(0));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest();
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(3));
|
||||
assertThat(getAliasesResponse.getAliases().get("index1").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData1 = getAliasesResponse.getAliases().get("index1").iterator().next();
|
||||
assertThat(aliasMetaData1, notNullValue());
|
||||
assertThat(aliasMetaData1.alias(), equalTo("alias1"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index2").size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData2 = getAliasesResponse.getAliases().get("index2").iterator().next();
|
||||
assertThat(aliasMetaData2, notNullValue());
|
||||
assertThat(aliasMetaData2.alias(), equalTo("alias2"));
|
||||
assertThat(getAliasesResponse.getAliases().get("index3").size(), equalTo(0));
|
||||
}
|
||||
}
|
||||
|
||||
public void testGetAliasesNonExistentIndexOrAlias() throws IOException {
|
||||
/*
|
||||
* This test is quite extensive as this is the only way we can check that we haven't slid out of sync with the server
|
||||
* because the server renders the xcontent in a spot that is difficult for us to access in a unit test.
|
||||
*/
|
||||
String alias = "alias";
|
||||
String index = "index";
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices(index);
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(getAliasesResponse.getException().getMessage(),
|
||||
equalTo("Elasticsearch exception [type=index_not_found_exception, reason=no such index]"));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest(alias);
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(getAliasesResponse.getError(), equalTo("alias [" + alias + "] missing"));
|
||||
}
|
||||
createIndex(index, Settings.EMPTY);
|
||||
client().performRequest(HttpPut.METHOD_NAME, index + "/_alias/" + alias);
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices(index, "non_existent_index");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(getAliasesResponse.getException().getMessage(),
|
||||
equalTo("Elasticsearch exception [type=index_not_found_exception, reason=no such index]"));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices(index, "non_existent_index").aliases(alias);
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
assertThat(getAliasesResponse.getException().getMessage(),
|
||||
equalTo("Elasticsearch exception [type=index_not_found_exception, reason=no such index]"));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices("non_existent_index*");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(0));
|
||||
}
|
||||
{
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest().indices(index).aliases(alias, "non_existent_alias");
|
||||
GetAliasesResponse getAliasesResponse = execute(getAliasesRequest, highLevelClient().indices()::getAlias,
|
||||
highLevelClient().indices()::getAliasAsync);
|
||||
assertThat(getAliasesResponse.status(), equalTo(RestStatus.NOT_FOUND));
|
||||
|
||||
assertThat(getAliasesResponse.getAliases().size(), equalTo(1));
|
||||
assertThat(getAliasesResponse.getAliases().get(index).size(), equalTo(1));
|
||||
AliasMetaData aliasMetaData = getAliasesResponse.getAliases().get(index).iterator().next();
|
||||
assertThat(aliasMetaData, notNullValue());
|
||||
assertThat(aliasMetaData.alias(), equalTo(alias));
|
||||
/*
|
||||
This is the above response in json format:
|
||||
{
|
||||
"error": "alias [something] missing",
|
||||
"status": 404,
|
||||
"index": {
|
||||
"aliases": {
|
||||
"alias": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
public void testIndexPutSettings() throws IOException {
|
||||
|
||||
final Setting<Integer> dynamicSetting = IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING;
|
||||
|
|
|
@ -94,6 +94,7 @@ import org.elasticsearch.common.lucene.uid.Versions;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.util.CollectionUtils;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
|
@ -1563,6 +1564,36 @@ public class RequestConvertersTests extends ESTestCase {
|
|||
assertEquals(expectedParams, request.getParameters());
|
||||
}
|
||||
|
||||
public void testGetAlias() {
|
||||
GetAliasesRequest getAliasesRequest = new GetAliasesRequest();
|
||||
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
setRandomLocal(getAliasesRequest, expectedParams);
|
||||
setRandomIndicesOptions(getAliasesRequest::indicesOptions, getAliasesRequest::indicesOptions, expectedParams);
|
||||
|
||||
String[] indices = randomBoolean() ? null : randomIndicesNames(0, 2);
|
||||
String[] aliases = randomBoolean() ? null : randomIndicesNames(0, 2);
|
||||
getAliasesRequest.indices(indices);
|
||||
getAliasesRequest.aliases(aliases);
|
||||
|
||||
Request request = RequestConverters.getAlias(getAliasesRequest);
|
||||
StringJoiner expectedEndpoint = new StringJoiner("/", "/", "");
|
||||
|
||||
if (false == CollectionUtils.isEmpty(indices)) {
|
||||
expectedEndpoint.add(String.join(",", indices));
|
||||
}
|
||||
expectedEndpoint.add("_alias");
|
||||
|
||||
if (false == CollectionUtils.isEmpty(aliases)) {
|
||||
expectedEndpoint.add(String.join(",", aliases));
|
||||
}
|
||||
|
||||
assertEquals(HttpGet.METHOD_NAME, request.getMethod());
|
||||
assertEquals(expectedEndpoint.toString(), request.getEndpoint());
|
||||
assertEquals(expectedParams, request.getParameters());
|
||||
assertNull(request.getEntity());
|
||||
}
|
||||
|
||||
public void testIndexPutSettings() throws IOException {
|
||||
String[] indices = randomBoolean() ? null : randomIndicesNames(0, 2);
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(indices);
|
||||
|
|
|
@ -51,10 +51,10 @@ import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
|||
import org.elasticsearch.action.admin.indices.refresh.RefreshResponse;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
||||
|
@ -66,9 +66,11 @@ import org.elasticsearch.action.support.ActiveShardCount;
|
|||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
||||
import org.elasticsearch.client.GetAliasesResponse;
|
||||
import org.elasticsearch.client.RequestOptions;
|
||||
import org.elasticsearch.client.RestHighLevelClient;
|
||||
import org.elasticsearch.client.SyncedFlushResponse;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MappingMetaData;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
|
@ -87,6 +89,7 @@ import java.util.Arrays;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -1726,6 +1729,75 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
|
|||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
public void testGetAlias() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
{
|
||||
CreateIndexResponse createIndexResponse = client.indices().create(new CreateIndexRequest("index").alias(new Alias("alias")));
|
||||
assertTrue(createIndexResponse.isAcknowledged());
|
||||
}
|
||||
|
||||
{
|
||||
// tag::get-alias-request
|
||||
GetAliasesRequest request = new GetAliasesRequest();
|
||||
GetAliasesRequest requestWithAlias = new GetAliasesRequest("alias1");
|
||||
GetAliasesRequest requestWithAliases =
|
||||
new GetAliasesRequest(new String[]{"alias1", "alias2"});
|
||||
// end::get-alias-request
|
||||
|
||||
// tag::get-alias-request-alias
|
||||
request.aliases("alias"); // <1>
|
||||
// end::get-alias-request-alias
|
||||
// tag::get-alias-request-indices
|
||||
request.indices("index"); // <1>
|
||||
// end::get-alias-request-indices
|
||||
|
||||
// tag::get-alias-request-indicesOptions
|
||||
request.indicesOptions(IndicesOptions.lenientExpandOpen()); // <1>
|
||||
// end::get-alias-request-indicesOptions
|
||||
|
||||
// tag::get-alias-request-local
|
||||
request.local(true); // <1>
|
||||
// end::get-alias-request-local
|
||||
|
||||
// tag::get-alias-execute
|
||||
GetAliasesResponse response = client.indices().getAlias(request, RequestOptions.DEFAULT);
|
||||
// end::get-alias-execute
|
||||
|
||||
// tag::get-alias-response
|
||||
Map<String, Set<AliasMetaData>> aliases = response.getAliases(); // <1>
|
||||
// end::get-alias-response
|
||||
|
||||
assertThat(response.getAliases().get("index").size(), equalTo(1));
|
||||
assertThat(response.getAliases().get("index").iterator().next().alias(), equalTo("alias"));
|
||||
|
||||
// tag::get-alias-listener
|
||||
ActionListener<GetAliasesResponse> listener =
|
||||
new ActionListener<GetAliasesResponse>() {
|
||||
@Override
|
||||
public void onResponse(GetAliasesResponse getAliasesResponse) {
|
||||
// <1>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// <2>
|
||||
}
|
||||
};
|
||||
// end::get-alias-listener
|
||||
|
||||
// Replace the empty listener by a blocking listener in test
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
listener = new LatchedActionListener<>(listener, latch);
|
||||
|
||||
// tag::get-alias-execute-async
|
||||
client.indices().getAliasAsync(request, RequestOptions.DEFAULT, listener); // <1>
|
||||
// end::get-alias-execute-async
|
||||
|
||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
public void testIndexPutSettings() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
[[java-rest-high-get-alias]]
|
||||
=== Get Alias API
|
||||
|
||||
[[java-rest-high-get-alias-request]]
|
||||
==== Get Alias Request
|
||||
|
||||
The Get Alias API uses `GetAliasesRequest` as its request object.
|
||||
One or more aliases can be optionally provided either at construction
|
||||
time or later on through the relevant setter method.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-request]
|
||||
--------------------------------------------------
|
||||
|
||||
==== Optional arguments
|
||||
The following arguments can optionally be provided:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-request-alias]
|
||||
--------------------------------------------------
|
||||
<1> One or more aliases to retrieve
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-request-indices]
|
||||
--------------------------------------------------
|
||||
<1> The index or indices that the alias is associated with
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-request-indicesOptions]
|
||||
--------------------------------------------------
|
||||
<1> Setting `IndicesOptions` controls how unavailable indices are resolved and
|
||||
how wildcard expressions are expanded when looking for aliases that belong to
|
||||
specified indices.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-request-local]
|
||||
--------------------------------------------------
|
||||
<1> The `local` flag (defaults to `false`) controls whether the aliases need
|
||||
to be looked up in the local cluster state or in the cluster state held by
|
||||
the elected master node
|
||||
|
||||
[[java-rest-high-get-alias-sync]]
|
||||
==== Synchronous Execution
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-execute]
|
||||
--------------------------------------------------
|
||||
|
||||
[[java-rest-high-get-alias-async]]
|
||||
==== Asynchronous Execution
|
||||
|
||||
The asynchronous execution of a get alias request requires both a `GetAliasesRequest`
|
||||
instance and an `ActionListener` instance to be passed to the asynchronous
|
||||
method:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-execute-async]
|
||||
--------------------------------------------------
|
||||
<1> The `GetAliasesRequest` to execute and the `ActionListener` to use when
|
||||
the execution completes
|
||||
|
||||
The asynchronous method does not block and returns immediately. Once it is
|
||||
completed the `ActionListener` is called back using the `onResponse` method
|
||||
if the execution successfully completed or using the `onFailure` method if
|
||||
it failed.
|
||||
|
||||
A typical listener for the `Boolean` response looks like:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-listener]
|
||||
--------------------------------------------------
|
||||
<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-get-alias-response]]
|
||||
==== Get Alias Response
|
||||
|
||||
The returned `GetAliasesResponse` allows to retrieve information about the
|
||||
executed operation as follows:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-alias-response]
|
||||
--------------------------------------------------
|
||||
<1> Retrieves a map of indices and their aliases
|
|
@ -80,6 +80,7 @@ Mapping Management::
|
|||
Alias Management::
|
||||
* <<java-rest-high-update-aliases>>
|
||||
* <<java-rest-high-exists-alias>>
|
||||
* <<java-rest-high-get-alias>>
|
||||
|
||||
include::indices/create_index.asciidoc[]
|
||||
include::indices/delete_index.asciidoc[]
|
||||
|
@ -98,6 +99,7 @@ include::indices/put_mapping.asciidoc[]
|
|||
include::indices/get_mappings.asciidoc[]
|
||||
include::indices/update_aliases.asciidoc[]
|
||||
include::indices/exists_alias.asciidoc[]
|
||||
include::indices/get_alias.asciidoc[]
|
||||
include::indices/put_settings.asciidoc[]
|
||||
include::indices/get_settings.asciidoc[]
|
||||
include::indices/put_template.asciidoc[]
|
||||
|
|
|
@ -420,7 +420,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
|
|||
return innerFromXContent(parser, false);
|
||||
}
|
||||
|
||||
private static ElasticsearchException innerFromXContent(XContentParser parser, boolean parseRootCauses) throws IOException {
|
||||
public static ElasticsearchException innerFromXContent(XContentParser parser, boolean parseRootCauses) throws IOException {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class GetAliasesResponse extends ActionResponse {
|
||||
|
||||
|
@ -42,7 +43,6 @@ public class GetAliasesResponse extends ActionResponse {
|
|||
GetAliasesResponse() {
|
||||
}
|
||||
|
||||
|
||||
public ImmutableOpenMap<String, List<AliasMetaData>> getAliases() {
|
||||
return aliases;
|
||||
}
|
||||
|
@ -76,4 +76,21 @@ public class GetAliasesResponse extends ActionResponse {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
GetAliasesResponse that = (GetAliasesResponse) o;
|
||||
return Objects.equals(aliases, that.aliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(aliases);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,5 +65,4 @@ public class TransportGetAliasesAction extends TransportMasterNodeReadAction<Get
|
|||
ImmutableOpenMap<String, List<AliasMetaData>> result = state.metaData().findAliases(request.aliases(), concreteIndices);
|
||||
listener.onResponse(new GetAliasesResponse(result));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -348,5 +348,4 @@ public class AliasMetaData extends AbstractDiffable<AliasMetaData> implements To
|
|||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.rest.action.admin.indices;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
|
@ -84,6 +83,8 @@ public class RestGetAliasesAction extends BaseRestHandler {
|
|||
getAliasesRequest.indicesOptions(IndicesOptions.fromRequest(request, getAliasesRequest.indicesOptions()));
|
||||
getAliasesRequest.local(request.paramAsBoolean("local", getAliasesRequest.local()));
|
||||
|
||||
//we may want to move this logic to TransportGetAliasesAction but it is based on the original provided aliases, which will
|
||||
//not always be available there (they may get replaced so retrieving request.aliases is not quite the same).
|
||||
return channel -> client.admin().indices().getAliases(getAliasesRequest, new RestBuilderListener<GetAliasesResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(GetAliasesResponse response, XContentBuilder builder) throws Exception {
|
||||
|
@ -127,9 +128,11 @@ public class RestGetAliasesAction extends BaseRestHandler {
|
|||
status = RestStatus.NOT_FOUND;
|
||||
final String message;
|
||||
if (difference.size() == 1) {
|
||||
message = String.format(Locale.ROOT, "alias [%s] missing", toNamesString(difference.iterator().next()));
|
||||
message = String.format(Locale.ROOT, "alias [%s] missing",
|
||||
Strings.collectionToCommaDelimitedString(difference));
|
||||
} else {
|
||||
message = String.format(Locale.ROOT, "aliases [%s] missing", toNamesString(difference.toArray(new String[0])));
|
||||
message = String.format(Locale.ROOT, "aliases [%s] missing",
|
||||
Strings.collectionToCommaDelimitedString(difference));
|
||||
}
|
||||
builder.field("error", message);
|
||||
builder.field("status", status.getStatus());
|
||||
|
@ -158,14 +161,4 @@ public class RestGetAliasesAction extends BaseRestHandler {
|
|||
});
|
||||
}
|
||||
|
||||
private static String toNamesString(final String... names) {
|
||||
if (names == null || names.length == 0) {
|
||||
return "";
|
||||
} else if (names.length == 1) {
|
||||
return names[0];
|
||||
} else {
|
||||
return Arrays.stream(names).collect(Collectors.joining(","));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.alias.get;
|
||||
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData.Builder;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.test.AbstractStreamableTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class GetAliasesResponseTests extends AbstractStreamableTestCase<GetAliasesResponse> {
|
||||
|
||||
@Override
|
||||
protected GetAliasesResponse createTestInstance() {
|
||||
return createTestItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetAliasesResponse createBlankInstance() {
|
||||
return new GetAliasesResponse();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GetAliasesResponse mutateInstance(GetAliasesResponse response) {
|
||||
return new GetAliasesResponse(mutateAliases(response.getAliases()));
|
||||
}
|
||||
|
||||
private static ImmutableOpenMap<String, List<AliasMetaData>> mutateAliases(ImmutableOpenMap<String, List<AliasMetaData>> aliases) {
|
||||
if (aliases.isEmpty()) {
|
||||
return createIndicesAliasesMap(1, 3).build();
|
||||
}
|
||||
|
||||
if (randomBoolean()) {
|
||||
ImmutableOpenMap.Builder<String, List<AliasMetaData>> builder = ImmutableOpenMap.builder(aliases);
|
||||
ImmutableOpenMap<String, List<AliasMetaData>> list = createIndicesAliasesMap(1, 2).build();
|
||||
list.forEach(e -> builder.put(e.key, e.value));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Set<String> indices = new HashSet<>();
|
||||
Iterator<String> keys = aliases.keysIt();
|
||||
while (keys.hasNext()) {
|
||||
indices.add(keys.next());
|
||||
}
|
||||
|
||||
List<String> indicesToBeModified = randomSubsetOf(randomIntBetween(1, indices.size()), indices);
|
||||
ImmutableOpenMap.Builder<String, List<AliasMetaData>> builder = ImmutableOpenMap.builder();
|
||||
|
||||
for (String index : indices) {
|
||||
List<AliasMetaData> list = new ArrayList<>(aliases.get(index));
|
||||
if (indicesToBeModified.contains(index)) {
|
||||
if (randomBoolean() || list.isEmpty()) {
|
||||
list.add(createAliasMetaData());
|
||||
} else {
|
||||
int aliasIndex = randomInt(list.size() - 1);
|
||||
AliasMetaData aliasMetaData = list.get(aliasIndex);
|
||||
list.add(aliasIndex, mutateAliasMetaData(aliasMetaData));
|
||||
}
|
||||
}
|
||||
builder.put(index, list);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static GetAliasesResponse createTestItem() {
|
||||
return new GetAliasesResponse(createIndicesAliasesMap(0, 5).build());
|
||||
}
|
||||
|
||||
private static ImmutableOpenMap.Builder<String, List<AliasMetaData>> createIndicesAliasesMap(int min, int max) {
|
||||
ImmutableOpenMap.Builder<String, List<AliasMetaData>> builder = ImmutableOpenMap.builder();
|
||||
int indicesNum = randomIntBetween(min, max);
|
||||
for (int i = 0; i < indicesNum; i++) {
|
||||
String index = randomAlphaOfLength(5);
|
||||
List<AliasMetaData> aliasMetaData = new ArrayList<>();
|
||||
int aliasesNum = randomIntBetween(0, 3);
|
||||
for (int alias = 0; alias < aliasesNum; alias++) {
|
||||
aliasMetaData.add(createAliasMetaData());
|
||||
}
|
||||
builder.put(index, aliasMetaData);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static AliasMetaData createAliasMetaData() {
|
||||
Builder builder = AliasMetaData.builder(randomAlphaOfLengthBetween(3, 10));
|
||||
if (randomBoolean()) {
|
||||
builder.routing(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
builder.searchRouting(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
builder.indexRouting(randomAlphaOfLengthBetween(3, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
builder.filter("{\"term\":{\"year\":2016}}");
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static AliasMetaData mutateAliasMetaData(AliasMetaData alias) {
|
||||
boolean changeAlias = randomBoolean();
|
||||
AliasMetaData.Builder builder = AliasMetaData.builder(changeAlias ? randomAlphaOfLengthBetween(2, 5) : alias.getAlias());
|
||||
builder.searchRouting(alias.searchRouting());
|
||||
builder.indexRouting(alias.indexRouting());
|
||||
builder.filter(alias.filter());
|
||||
|
||||
if (false == changeAlias) {
|
||||
if (randomBoolean()) {
|
||||
builder.searchRouting(alias.searchRouting() + randomAlphaOfLengthBetween(1, 3));
|
||||
} else {
|
||||
builder.indexRouting(alias.indexRouting() + randomAlphaOfLengthBetween(1, 3));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
|
@ -60,7 +60,7 @@ public final class XContentTestUtils {
|
|||
|
||||
|
||||
/**
|
||||
* Compares to maps generated from XContentObjects. The order of elements in arrays is ignored.
|
||||
* Compares two maps generated from XContentObjects. The order of elements in arrays is ignored.
|
||||
*
|
||||
* @return null if maps are equal or path to the element where the difference was found
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue