Add support to _aliases endpoint to specify multiple indices and aliases in one action
Closes #15305
This commit is contained in:
parent
b4e0c876d5
commit
bef0bedba9
|
@ -78,19 +78,19 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
indices(indices);
|
indices(indices);
|
||||||
aliases(aliases);
|
aliases(aliases);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AliasActions(AliasAction.Type type, String index, String alias) {
|
public AliasActions(AliasAction.Type type, String index, String alias) {
|
||||||
aliasAction = new AliasAction(type);
|
aliasAction = new AliasAction(type);
|
||||||
indices(index);
|
indices(index);
|
||||||
aliases(alias);
|
aliases(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
AliasActions(AliasAction.Type type, String[] index, String alias) {
|
AliasActions(AliasAction.Type type, String[] index, String alias) {
|
||||||
aliasAction = new AliasAction(type);
|
aliasAction = new AliasAction(type);
|
||||||
indices(index);
|
indices(index);
|
||||||
aliases(alias);
|
aliases(alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AliasActions(AliasAction action) {
|
public AliasActions(AliasAction action) {
|
||||||
this.aliasAction = action;
|
this.aliasAction = action;
|
||||||
indices(action.index());
|
indices(action.index());
|
||||||
|
@ -110,7 +110,7 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
aliasAction.filter(filter);
|
aliasAction.filter(filter);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AliasActions filter(QueryBuilder filter) {
|
public AliasActions filter(QueryBuilder filter) {
|
||||||
aliasAction.filter(filter);
|
aliasAction.filter(filter);
|
||||||
return this;
|
return this;
|
||||||
|
@ -197,7 +197,7 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
aliasAction = readAliasAction(in);
|
aliasAction = readAliasAction(in);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
out.writeStringArray(indices);
|
out.writeStringArray(indices);
|
||||||
out.writeStringArray(aliases);
|
out.writeStringArray(aliases);
|
||||||
|
@ -225,7 +225,7 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
addAliasAction(new AliasActions(action));
|
addAliasAction(new AliasActions(action));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an alias to the index.
|
* Adds an alias to the index.
|
||||||
* @param alias The alias
|
* @param alias The alias
|
||||||
|
@ -247,8 +247,8 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
addAliasAction(new AliasActions(AliasAction.Type.ADD, indices, alias).filter(filterBuilder));
|
addAliasAction(new AliasActions(AliasAction.Type.ADD, indices, alias).filter(filterBuilder));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an alias to the index.
|
* Removes an alias to the index.
|
||||||
*
|
*
|
||||||
|
@ -259,7 +259,7 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
addAliasAction(new AliasActions(AliasAction.Type.REMOVE, indices, aliases));
|
addAliasAction(new AliasActions(AliasAction.Type.REMOVE, indices, aliases));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an alias to the index.
|
* Removes an alias to the index.
|
||||||
*
|
*
|
||||||
|
@ -286,25 +286,14 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
return addValidationError("Must specify at least one alias action", validationException);
|
return addValidationError("Must specify at least one alias action", validationException);
|
||||||
}
|
}
|
||||||
for (AliasActions aliasAction : allAliasActions) {
|
for (AliasActions aliasAction : allAliasActions) {
|
||||||
if (aliasAction.actionType() == AliasAction.Type.ADD) {
|
if (aliasAction.aliases.length == 0) {
|
||||||
if (aliasAction.aliases.length != 1) {
|
validationException = addValidationError("Alias action [" + aliasAction.actionType().name().toLowerCase(Locale.ENGLISH)
|
||||||
|
+ "]: aliases may not be empty", validationException);
|
||||||
|
}
|
||||||
|
for (String alias : aliasAction.aliases) {
|
||||||
|
if (!Strings.hasText(alias)) {
|
||||||
validationException = addValidationError("Alias action [" + aliasAction.actionType().name().toLowerCase(Locale.ENGLISH)
|
validationException = addValidationError("Alias action [" + aliasAction.actionType().name().toLowerCase(Locale.ENGLISH)
|
||||||
+ "] requires exactly one [alias] to be set", validationException);
|
+ "]: [alias] may not be empty string", validationException);
|
||||||
}
|
|
||||||
if (!Strings.hasText(aliasAction.aliases[0])) {
|
|
||||||
validationException = addValidationError("Alias action [" + aliasAction.actionType().name().toLowerCase(Locale.ENGLISH)
|
|
||||||
+ "] requires an [alias] to be set", validationException);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (aliasAction.aliases.length == 0) {
|
|
||||||
validationException = addValidationError("Alias action [" + aliasAction.actionType().name().toLowerCase(Locale.ENGLISH)
|
|
||||||
+ "]: aliases may not be empty", validationException);
|
|
||||||
}
|
|
||||||
for (String alias : aliasAction.aliases) {
|
|
||||||
if (!Strings.hasText(alias)) {
|
|
||||||
validationException = addValidationError("Alias action [" + aliasAction.actionType().name().toLowerCase(Locale.ENGLISH)
|
|
||||||
+ "]: [alias] may not be empty string", validationException);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CollectionUtils.isEmpty(aliasAction.indices)) {
|
if (CollectionUtils.isEmpty(aliasAction.indices)) {
|
||||||
|
@ -345,7 +334,7 @@ public class IndicesAliasesRequest extends AcknowledgedRequest<IndicesAliasesReq
|
||||||
public IndicesOptions indicesOptions() {
|
public IndicesOptions indicesOptions() {
|
||||||
return INDICES_OPTIONS;
|
return INDICES_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AliasActions readAliasActions(StreamInput in) throws IOException {
|
private static AliasActions readAliasActions(StreamInput in) throws IOException {
|
||||||
AliasActions actions = new AliasActions();
|
AliasActions actions = new AliasActions();
|
||||||
return actions.readFrom(in);
|
return actions.readFrom(in);
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
package org.elasticsearch.rest.action.admin.indices.alias;
|
package org.elasticsearch.rest.action.admin.indices.alias;
|
||||||
|
|
||||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||||
|
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
|
||||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
|
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
|
||||||
import org.elasticsearch.client.Client;
|
import org.elasticsearch.client.Client;
|
||||||
import org.elasticsearch.cluster.metadata.AliasAction;
|
import org.elasticsearch.cluster.metadata.AliasAction;
|
||||||
|
@ -30,9 +31,10 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.rest.*;
|
import org.elasticsearch.rest.*;
|
||||||
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
|
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.elasticsearch.cluster.metadata.AliasAction.newAddAliasAction;
|
|
||||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,8 +77,8 @@ public class RestIndicesAliasesAction extends BaseRestHandler {
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Alias action [" + action + "] not supported");
|
throw new IllegalArgumentException("Alias action [" + action + "] not supported");
|
||||||
}
|
}
|
||||||
String index = null;
|
String[] indices = null;
|
||||||
String alias = null;
|
String[] aliases = null;
|
||||||
Map<String, Object> filter = null;
|
Map<String, Object> filter = null;
|
||||||
String routing = null;
|
String routing = null;
|
||||||
boolean routingSet = false;
|
boolean routingSet = false;
|
||||||
|
@ -90,9 +92,9 @@ public class RestIndicesAliasesAction extends BaseRestHandler {
|
||||||
currentFieldName = parser.currentName();
|
currentFieldName = parser.currentName();
|
||||||
} else if (token.isValue()) {
|
} else if (token.isValue()) {
|
||||||
if ("index".equals(currentFieldName)) {
|
if ("index".equals(currentFieldName)) {
|
||||||
index = parser.text();
|
indices = new String[] { parser.text() };
|
||||||
} else if ("alias".equals(currentFieldName)) {
|
} else if ("alias".equals(currentFieldName)) {
|
||||||
alias = parser.text();
|
aliases = new String[] { parser.text() };
|
||||||
} else if ("routing".equals(currentFieldName)) {
|
} else if ("routing".equals(currentFieldName)) {
|
||||||
routing = parser.textOrNull();
|
routing = parser.textOrNull();
|
||||||
routingSet = true;
|
routingSet = true;
|
||||||
|
@ -103,6 +105,23 @@ public class RestIndicesAliasesAction extends BaseRestHandler {
|
||||||
searchRouting = parser.textOrNull();
|
searchRouting = parser.textOrNull();
|
||||||
searchRoutingSet = true;
|
searchRoutingSet = true;
|
||||||
}
|
}
|
||||||
|
} else if (token == XContentParser.Token.START_ARRAY) {
|
||||||
|
if ("indices".equals(currentFieldName)) {
|
||||||
|
List<String> indexNames = new ArrayList<>();
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
String index = parser.text();
|
||||||
|
indexNames.add(index);
|
||||||
|
}
|
||||||
|
indices = indexNames.toArray(new String[indexNames.size()]);
|
||||||
|
}
|
||||||
|
if ("aliases".equals(currentFieldName)) {
|
||||||
|
List<String> aliasNames = new ArrayList<>();
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
String alias = parser.text();
|
||||||
|
aliasNames.add(alias);
|
||||||
|
}
|
||||||
|
aliases = aliasNames.toArray(new String[aliasNames.size()]);
|
||||||
|
}
|
||||||
} else if (token == XContentParser.Token.START_OBJECT) {
|
} else if (token == XContentParser.Token.START_OBJECT) {
|
||||||
if ("filter".equals(currentFieldName)) {
|
if ("filter".equals(currentFieldName)) {
|
||||||
filter = parser.mapOrdered();
|
filter = parser.mapOrdered();
|
||||||
|
@ -111,19 +130,19 @@ public class RestIndicesAliasesAction extends BaseRestHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == AliasAction.Type.ADD) {
|
if (type == AliasAction.Type.ADD) {
|
||||||
AliasAction aliasAction = newAddAliasAction(index, alias).filter(filter);
|
AliasActions aliasActions = new AliasActions(type, indices, aliases);
|
||||||
if (routingSet) {
|
if (routingSet) {
|
||||||
aliasAction.routing(routing);
|
aliasActions.routing(routing);
|
||||||
}
|
}
|
||||||
if (indexRoutingSet) {
|
if (indexRoutingSet) {
|
||||||
aliasAction.indexRouting(indexRouting);
|
aliasActions.indexRouting(indexRouting);
|
||||||
}
|
}
|
||||||
if (searchRoutingSet) {
|
if (searchRoutingSet) {
|
||||||
aliasAction.searchRouting(searchRouting);
|
aliasActions.searchRouting(searchRouting);
|
||||||
}
|
}
|
||||||
indicesAliasesRequest.addAliasAction(aliasAction);
|
indicesAliasesRequest.addAliasAction(aliasActions);
|
||||||
} else if (type == AliasAction.Type.REMOVE) {
|
} else if (type == AliasAction.Type.REMOVE) {
|
||||||
indicesAliasesRequest.removeAlias(index, alias);
|
indicesAliasesRequest.removeAlias(indices, aliases);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -759,7 +759,7 @@ public class IndexAliasesIT extends ESIntegTestCase {
|
||||||
admin().indices().prepareAliases().addAliasAction(AliasAction.newAddAliasAction("index1", null)).get();
|
admin().indices().prepareAliases().addAliasAction(AliasAction.newAddAliasAction("index1", null)).get();
|
||||||
fail("Expected ActionRequestValidationException");
|
fail("Expected ActionRequestValidationException");
|
||||||
} catch (ActionRequestValidationException e) {
|
} catch (ActionRequestValidationException e) {
|
||||||
assertThat(e.getMessage(), containsString("requires an [alias] to be set"));
|
assertThat(e.getMessage(), containsString("[alias] may not be empty string"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,7 +768,7 @@ public class IndexAliasesIT extends ESIntegTestCase {
|
||||||
admin().indices().prepareAliases().addAliasAction(AliasAction.newAddAliasAction("index1", "")).get();
|
admin().indices().prepareAliases().addAliasAction(AliasAction.newAddAliasAction("index1", "")).get();
|
||||||
fail("Expected ActionRequestValidationException");
|
fail("Expected ActionRequestValidationException");
|
||||||
} catch (ActionRequestValidationException e) {
|
} catch (ActionRequestValidationException e) {
|
||||||
assertThat(e.getMessage(), containsString("requires an [alias] to be set"));
|
assertThat(e.getMessage(), containsString("[alias] may not be empty string"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,22 @@ curl -XPOST 'http://localhost:9200/_aliases' -d '
|
||||||
}'
|
}'
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
Alternatively, you can use a glob pattern to associate an alias to
|
Multiple indices can be specified for an action with the `indices` array syntax:
|
||||||
|
|
||||||
|
[source,js]
|
||||||
|
--------------------------------------------------
|
||||||
|
curl -XPOST 'http://localhost:9200/_aliases' -d '
|
||||||
|
{
|
||||||
|
"actions" : [
|
||||||
|
{ "add" : { "indices" : ["test1", "test2"], "alias" : "alias1" } }
|
||||||
|
]
|
||||||
|
}'
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
To specify multiple aliases in one action, the corresponding `aliases` array
|
||||||
|
syntax exists as well.
|
||||||
|
|
||||||
|
For the example above, a glob pattern can also be used to associate an alias to
|
||||||
more than one index that share a common name:
|
more than one index that share a common name:
|
||||||
|
|
||||||
[source,js]
|
[source,js]
|
||||||
|
|
|
@ -32,3 +32,50 @@
|
||||||
name: test_alias
|
name: test_alias
|
||||||
|
|
||||||
- match: {test_index.aliases.test_alias: {'index_routing': 'routing_value', 'search_routing': 'routing_value'}}
|
- match: {test_index.aliases.test_alias: {'index_routing': 'routing_value', 'search_routing': 'routing_value'}}
|
||||||
|
|
||||||
|
---
|
||||||
|
"Basic test for multiple aliases":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.create:
|
||||||
|
index: test_index
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.exists_alias:
|
||||||
|
name: test_alias1
|
||||||
|
|
||||||
|
- is_false: ''
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.exists_alias:
|
||||||
|
name: test_alias2
|
||||||
|
|
||||||
|
- is_false: ''
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.update_aliases:
|
||||||
|
body:
|
||||||
|
actions:
|
||||||
|
- add:
|
||||||
|
indices: [test_index]
|
||||||
|
aliases: [test_alias1, test_alias2]
|
||||||
|
routing: routing_value
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.exists_alias:
|
||||||
|
name: test_alias1
|
||||||
|
|
||||||
|
- is_true: ''
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.exists_alias:
|
||||||
|
name: test_alias2
|
||||||
|
|
||||||
|
- is_true: ''
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_alias:
|
||||||
|
index: test_index
|
||||||
|
|
||||||
|
- match: {test_index.aliases.test_alias1: {'index_routing': 'routing_value', 'search_routing': 'routing_value'}}
|
||||||
|
- match: {test_index.aliases.test_alias2: {'index_routing': 'routing_value', 'search_routing': 'routing_value'}}
|
||||||
|
|
Loading…
Reference in New Issue