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:
olcbean 2018-06-12 10:26:17 +02:00 committed by Luca Cavanna
parent a178290b60
commit 7d7ead95b2
17 changed files with 1001 additions and 48 deletions

View File

@ -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;
}
}

View File

@ -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.get.GetIndexTemplatesResponse;
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException; import java.io.IOException;
import java.util.Collections; import java.util.Collections;
import static java.util.Collections.emptySet; 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. * 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); 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. * 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 * See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-update-settings.html"> Update Indices Settings

View File

@ -831,6 +831,17 @@ final class RequestConverters {
return request; 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 { static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) throws IOException {
String[] names = getIndexTemplatesRequest.names(); String[] names = getIndexTemplatesRequest.names();
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addCommaSeparatedPathParts(names).build(); String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addCommaSeparatedPathParts(names).build();

View File

@ -1021,10 +1021,10 @@ public class RestHighLevelClient implements Closeable {
try { try {
return responseConverter.apply(e.getResponse()); return responseConverter.apply(e.getResponse());
} catch (Exception innerException) { } catch (Exception innerException) {
//the exception is ignored as we now try to parse the response 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, // 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 // 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. // first. If parsing of the response breaks, we fall back to parsing it as an error.
throw parseResponseException(e); throw parseResponseException(e);
} }
} }
@ -1109,10 +1109,10 @@ public class RestHighLevelClient implements Closeable {
try { try {
actionListener.onResponse(responseConverter.apply(response)); actionListener.onResponse(responseConverter.apply(response));
} catch (Exception innerException) { } catch (Exception innerException) {
//the exception is ignored as we now try to parse the response 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, // 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 // 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. // first. If parsing of the response breaks, we fall back to parsing it as an error.
actionListener.onFailure(parseResponseException(responseException)); actionListener.onFailure(parseResponseException(responseException));
} }
} else { } else {

View File

@ -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());
}
}
}

View File

@ -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.refresh.RefreshResponse;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest; import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse; 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.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; 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.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse; import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType; 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.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.action.support.broadcast.BroadcastResponse;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
import org.elasticsearch.common.ValidationException; 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.hasEntry;
import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.startsWith; import static org.hamcrest.Matchers.startsWith;
public class IndicesClientIT extends ESRestHighLevelClientTestCase { public class IndicesClientIT extends ESRestHighLevelClientTestCase {
@ -320,8 +323,8 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
assertEquals(0, getSettingsResponse.getIndexToSettings().get("get_settings_index").size()); assertEquals(0, getSettingsResponse.getIndexToSettings().get("get_settings_index").size());
assertEquals(1, getSettingsResponse.getIndexToDefaultSettings().get("get_settings_index").size()); assertEquals(1, getSettingsResponse.getIndexToDefaultSettings().get("get_settings_index").size());
} }
public void testPutMapping() throws IOException { public void testPutMapping() throws IOException {
{
// Add mappings to index // Add mappings to index
String indexName = "mapping_index"; String indexName = "mapping_index";
createIndex(indexName, Settings.EMPTY); createIndex(indexName, Settings.EMPTY);
@ -342,7 +345,6 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
Map<String, Object> getIndexResponse = getAsMap(indexName); Map<String, Object> getIndexResponse = getAsMap(indexName);
assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse)); assertEquals("text", XContentMapValues.extractValue(indexName + ".mappings.type_name.properties.field.type", getIndexResponse));
} }
}
public void testGetMapping() throws IOException { public void testGetMapping() throws IOException {
String indexName = "test"; String indexName = "test";
@ -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 { public void testIndexPutSettings() throws IOException {
final Setting<Integer> dynamicSetting = IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING; final Setting<Integer> dynamicSetting = IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING;

View File

@ -94,6 +94,7 @@ import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit; import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.CollectionUtils;
import org.elasticsearch.common.xcontent.ToXContent; import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentHelper; import org.elasticsearch.common.xcontent.XContentHelper;
@ -1563,6 +1564,36 @@ public class RequestConvertersTests extends ESTestCase {
assertEquals(expectedParams, request.getParameters()); 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 { public void testIndexPutSettings() throws IOException {
String[] indices = randomBoolean() ? null : randomIndicesNames(0, 2); String[] indices = randomBoolean() ? null : randomIndicesNames(0, 2);
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(indices); UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(indices);

View File

@ -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.refresh.RefreshResponse;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest; import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse; 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.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; 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.ResizeRequest;
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse; import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
import org.elasticsearch.action.admin.indices.shrink.ResizeType; 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.DefaultShardOperationFailedException;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.ESRestHighLevelClientTestCase; import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.GetAliasesResponse;
import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.SyncedFlushResponse; import org.elasticsearch.client.SyncedFlushResponse;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.collect.ImmutableOpenMap;
@ -87,6 +89,7 @@ import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -1726,6 +1729,75 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
assertTrue(latch.await(30L, TimeUnit.SECONDS)); 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 { public void testIndexPutSettings() throws Exception {
RestHighLevelClient client = highLevelClient(); RestHighLevelClient client = highLevelClient();

View File

@ -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

View File

@ -80,6 +80,7 @@ Mapping Management::
Alias Management:: Alias Management::
* <<java-rest-high-update-aliases>> * <<java-rest-high-update-aliases>>
* <<java-rest-high-exists-alias>> * <<java-rest-high-exists-alias>>
* <<java-rest-high-get-alias>>
include::indices/create_index.asciidoc[] include::indices/create_index.asciidoc[]
include::indices/delete_index.asciidoc[] include::indices/delete_index.asciidoc[]
@ -98,6 +99,7 @@ include::indices/put_mapping.asciidoc[]
include::indices/get_mappings.asciidoc[] include::indices/get_mappings.asciidoc[]
include::indices/update_aliases.asciidoc[] include::indices/update_aliases.asciidoc[]
include::indices/exists_alias.asciidoc[] include::indices/exists_alias.asciidoc[]
include::indices/get_alias.asciidoc[]
include::indices/put_settings.asciidoc[] include::indices/put_settings.asciidoc[]
include::indices/get_settings.asciidoc[] include::indices/get_settings.asciidoc[]
include::indices/put_template.asciidoc[] include::indices/put_template.asciidoc[]

View File

@ -420,7 +420,7 @@ public class ElasticsearchException extends RuntimeException implements ToXConte
return innerFromXContent(parser, false); 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(); XContentParser.Token token = parser.currentToken();
ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation); ensureExpectedToken(XContentParser.Token.FIELD_NAME, token, parser::getTokenLocation);

View File

@ -30,6 +30,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
public class GetAliasesResponse extends ActionResponse { public class GetAliasesResponse extends ActionResponse {
@ -42,7 +43,6 @@ public class GetAliasesResponse extends ActionResponse {
GetAliasesResponse() { GetAliasesResponse() {
} }
public ImmutableOpenMap<String, List<AliasMetaData>> getAliases() { public ImmutableOpenMap<String, List<AliasMetaData>> getAliases() {
return aliases; 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);
}
} }

View File

@ -65,5 +65,4 @@ public class TransportGetAliasesAction extends TransportMasterNodeReadAction<Get
ImmutableOpenMap<String, List<AliasMetaData>> result = state.metaData().findAliases(request.aliases(), concreteIndices); ImmutableOpenMap<String, List<AliasMetaData>> result = state.metaData().findAliases(request.aliases(), concreteIndices);
listener.onResponse(new GetAliasesResponse(result)); listener.onResponse(new GetAliasesResponse(result));
} }
} }

View File

@ -348,5 +348,4 @@ public class AliasMetaData extends AbstractDiffable<AliasMetaData> implements To
return builder.build(); return builder.build();
} }
} }
} }

View File

@ -20,7 +20,6 @@
package org.elasticsearch.rest.action.admin.indices; package org.elasticsearch.rest.action.admin.indices;
import com.carrotsearch.hppc.cursors.ObjectObjectCursor; import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse; import org.elasticsearch.action.admin.indices.alias.get.GetAliasesResponse;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
@ -84,6 +83,8 @@ public class RestGetAliasesAction extends BaseRestHandler {
getAliasesRequest.indicesOptions(IndicesOptions.fromRequest(request, getAliasesRequest.indicesOptions())); getAliasesRequest.indicesOptions(IndicesOptions.fromRequest(request, getAliasesRequest.indicesOptions()));
getAliasesRequest.local(request.paramAsBoolean("local", getAliasesRequest.local())); 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) { return channel -> client.admin().indices().getAliases(getAliasesRequest, new RestBuilderListener<GetAliasesResponse>(channel) {
@Override @Override
public RestResponse buildResponse(GetAliasesResponse response, XContentBuilder builder) throws Exception { public RestResponse buildResponse(GetAliasesResponse response, XContentBuilder builder) throws Exception {
@ -127,9 +128,11 @@ public class RestGetAliasesAction extends BaseRestHandler {
status = RestStatus.NOT_FOUND; status = RestStatus.NOT_FOUND;
final String message; final String message;
if (difference.size() == 1) { 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 { } 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("error", message);
builder.field("status", status.getStatus()); 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(","));
}
}
} }

View File

@ -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();
}
}

View File

@ -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 * @return null if maps are equal or path to the element where the difference was found
*/ */