Added three new index alias related apis.

Added apis to get specific index aliases based on filtering by alias name and index name:
```
curl -XGET 'localhost:9200/{index_or_alias}/_alias/{alias_name}'
```

Added delete index alias api for deleting a single index alias:
```
curl -XDELETE 'localhost:9200/{index}/_alias/{alias_name}'
```

Added create index alias api for adding a single index alias:
```
curl -XPUT 'localhost:9200/{index}/_alias/{alias_name}'

curl -XPUT 'localhost:9200/{index}/_alias/{alias_name}' -d '{
	"routing" : {routing},
	"filter" : {filter}
}'

```

Closes #3075 #3076 #3077
This commit is contained in:
Martijn van Groningen 2013-05-17 12:29:24 +02:00
parent 841c2d1e14
commit ffdebe9bc3
15 changed files with 1059 additions and 4 deletions

View File

@ -42,6 +42,8 @@ import org.elasticsearch.action.admin.cluster.state.ClusterStateAction;
import org.elasticsearch.action.admin.cluster.state.TransportClusterStateAction;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction;
import org.elasticsearch.action.admin.indices.alias.TransportIndicesAliasesAction;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesAction;
import org.elasticsearch.action.admin.indices.alias.get.TransportIndicesGetAliasesAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.TransportAnalyzeAction;
import org.elasticsearch.action.admin.indices.cache.clear.ClearIndicesCacheAction;
@ -201,6 +203,7 @@ public class ActionModule extends AbstractModule {
registerAction(ClearIndicesCacheAction.INSTANCE, TransportClearIndicesCacheAction.class);
registerAction(PutWarmerAction.INSTANCE, TransportPutWarmerAction.class);
registerAction(DeleteWarmerAction.INSTANCE, TransportDeleteWarmerAction.class);
registerAction(IndicesGetAliasesAction.INSTANCE, TransportIndicesGetAliasesAction.class);
registerAction(IndexAction.INSTANCE, TransportIndexAction.class);
registerAction(GetAction.INSTANCE, TransportGetAction.class);

View File

@ -0,0 +1,45 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.action.admin.indices.IndicesAction;
import org.elasticsearch.client.IndicesAdminClient;
/**
*/
public class IndicesGetAliasesAction extends IndicesAction<IndicesGetAliasesRequest, IndicesGetAliasesResponse, IndicesGetAliasesRequestBuilder> {
public static final IndicesGetAliasesAction INSTANCE = new IndicesGetAliasesAction();
public static final String NAME = "indices/get/aliases";
private IndicesGetAliasesAction() {
super(NAME);
}
@Override
public IndicesGetAliasesRequestBuilder newRequestBuilder(IndicesAdminClient client) {
return new IndicesGetAliasesRequestBuilder(client);
}
@Override
public IndicesGetAliasesResponse newResponse() {
return new IndicesGetAliasesResponse();
}
}

View File

@ -0,0 +1,103 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.action.ActionRequestValidationException;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import static org.elasticsearch.action.ValidateActions.addValidationError;
/**
*/
public class IndicesGetAliasesRequest extends MasterNodeOperationRequest<IndicesGetAliasesRequest> {
private String[] indices = Strings.EMPTY_ARRAY;
private String[] aliases = Strings.EMPTY_ARRAY;
private IgnoreIndices ignoreIndices = IgnoreIndices.NONE;
public IndicesGetAliasesRequest(String[] aliases) {
this.aliases = aliases;
}
public IndicesGetAliasesRequest(String alias) {
this.aliases = new String[]{alias};
}
IndicesGetAliasesRequest() {
}
public IndicesGetAliasesRequest indices(String... indices) {
this.indices = indices;
return this;
}
public IndicesGetAliasesRequest aliases(String... aliases) {
this.aliases = aliases;
return this;
}
public IndicesGetAliasesRequest ignoreIndices(IgnoreIndices ignoreIndices) {
this.ignoreIndices = ignoreIndices;
return this;
}
public String[] indices() {
return indices;
}
public String[] aliases() {
return aliases;
}
public IgnoreIndices ignoreIndices() {
return ignoreIndices;
}
@Override
public ActionRequestValidationException validate() {
if (aliases.length == 0) {
return addValidationError("No alias specified", null);
} else {
return null;
}
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
indices = in.readStringArray();
aliases = in.readStringArray();
ignoreIndices = IgnoreIndices.fromId(in.readByte());
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringArray(indices);
out.writeStringArray(aliases);
out.writeByte(ignoreIndices.id());
}
}

View File

@ -0,0 +1,61 @@
/*
* Licensed to ElasticSearch and Shay Banon 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 com.google.common.collect.ObjectArrays;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.internal.InternalIndicesAdminClient;
/**
*/
public class IndicesGetAliasesRequestBuilder extends MasterNodeOperationRequestBuilder<IndicesGetAliasesRequest, IndicesGetAliasesResponse, IndicesGetAliasesRequestBuilder> {
public IndicesGetAliasesRequestBuilder(IndicesAdminClient client, String... aliases) {
super((InternalIndicesAdminClient)client, new IndicesGetAliasesRequest(aliases));
}
public IndicesGetAliasesRequestBuilder setAliases(String... aliases) {
request.aliases(aliases);
return this;
}
public IndicesGetAliasesRequestBuilder addAliases(String... aliases) {
request.aliases(ObjectArrays.concat(request.aliases(), aliases, String.class));
return this;
}
public IndicesGetAliasesRequestBuilder setIndices(String... indices) {
request.indices(indices);
return this;
}
public IndicesGetAliasesRequestBuilder addIndices(String... indices) {
request.indices(ObjectArrays.concat(request.indices(), indices, String.class));
return this;
}
@Override
protected void doExecute(ActionListener<IndicesGetAliasesResponse> listener) {
((IndicesAdminClient) client).getAliases(request, listener);
}
}

View File

@ -0,0 +1,78 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.action.ActionResponse;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*/
public class IndicesGetAliasesResponse extends ActionResponse {
private Map<String, List<AliasMetaData>> aliases = new HashMap<String, List<AliasMetaData>>();
public IndicesGetAliasesResponse(Map<String, List<AliasMetaData>> aliases) {
this.aliases = aliases;
}
IndicesGetAliasesResponse() {
}
public Map<String, List<AliasMetaData>> getAliases() {
return aliases;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
int size = in.readVInt();
for (int i = 0; i < size; i++) {
String key = in.readString();
int valueSize = in.readVInt();
List<AliasMetaData> value = new ArrayList<AliasMetaData>(valueSize);
for (int j = 0; j < valueSize; j++) {
value.add(AliasMetaData.Builder.readFrom(in));
}
aliases.put(key, value);
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeVInt(aliases.size());
for (Map.Entry<String, List<AliasMetaData>> entry : aliases.entrySet()) {
out.writeString(entry.getKey());
out.writeVInt(entry.getValue().size());
for (AliasMetaData aliasMetaData : entry.getValue()) {
AliasMetaData.Builder.writeTo(aliasMetaData, out);
}
}
}
}

View File

@ -0,0 +1,77 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.ElasticSearchException;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.indices.AliasMissingException;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import java.util.List;
import java.util.Map;
/**
*/
public class TransportIndicesGetAliasesAction extends TransportMasterNodeOperationAction<IndicesGetAliasesRequest, IndicesGetAliasesResponse> {
@Inject
public TransportIndicesGetAliasesAction(Settings settings, TransportService transportService, ClusterService clusterService, ThreadPool threadPool) {
super(settings, transportService, clusterService, threadPool);
}
@Override
protected String transportAction() {
return IndicesGetAliasesAction.NAME;
}
@Override
protected String executor() {
return ThreadPool.Names.MANAGEMENT;
}
@Override
protected IndicesGetAliasesRequest newRequest() {
return new IndicesGetAliasesRequest();
}
@Override
protected IndicesGetAliasesResponse newResponse() {
return new IndicesGetAliasesResponse();
}
@Override
protected IndicesGetAliasesResponse masterOperation(IndicesGetAliasesRequest request, ClusterState state) throws ElasticSearchException {
String[] concreteIndices = state.metaData().concreteIndices(request.indices(), request.ignoreIndices(), true);
request.indices(concreteIndices);
@SuppressWarnings("unchecked") // ImmutableList to List results incompatible type
Map<String, List<AliasMetaData>> result = (Map) state.metaData().findAliases(request.aliases(), request.indices());
if (result.isEmpty()) {
throw new AliasMissingException(request.aliases());
}
return new IndicesGetAliasesResponse(result);
}
}

View File

@ -24,6 +24,9 @@ import org.elasticsearch.action.admin.indices.IndicesAction;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesResponse;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeResponse;
@ -476,6 +479,26 @@ public interface IndicesAdminClient {
*/
IndicesAliasesRequestBuilder prepareAliases();
/**
* Get specific index aliases.
*
* @param request The result future
*/
ActionFuture<IndicesGetAliasesResponse> getAliases(IndicesGetAliasesRequest request);
/**
* Get specific index aliases.
*
* @param request The index aliases request
* @param listener A listener to be notified with a result
*/
void getAliases(IndicesGetAliasesRequest request, ActionListener<IndicesGetAliasesResponse> listener);
/**
* Adds specific index aliases.
*/
IndicesGetAliasesRequestBuilder prepareGetAliases(String... aliases);
/**
* Clear indices cache.
*

View File

@ -25,6 +25,10 @@ import org.elasticsearch.action.admin.indices.alias.IndicesAliasesAction;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesAction;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesRequestBuilder;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesResponse;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeAction;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequest;
import org.elasticsearch.action.admin.indices.analyze.AnalyzeRequestBuilder;
@ -175,6 +179,21 @@ public abstract class AbstractIndicesAdminClient implements InternalIndicesAdmin
return new IndicesAliasesRequestBuilder(this);
}
@Override
public ActionFuture<IndicesGetAliasesResponse> getAliases(IndicesGetAliasesRequest request) {
return execute(IndicesGetAliasesAction.INSTANCE, request);
}
@Override
public void getAliases(IndicesGetAliasesRequest request, ActionListener<IndicesGetAliasesResponse> listener) {
execute(IndicesGetAliasesAction.INSTANCE, request, listener);
}
@Override
public IndicesGetAliasesRequestBuilder prepareGetAliases(String... aliases) {
return new IndicesGetAliasesRequestBuilder(this, aliases);
}
@Override
public ActionFuture<ClearIndicesCacheResponse> clearCache(final ClearIndicesCacheRequest request) {
return execute(ClearIndicesCacheAction.INSTANCE, request);

View File

@ -19,10 +19,8 @@
package org.elasticsearch.cluster.metadata;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.UnmodifiableIterator;
import com.google.common.base.Predicate;
import com.google.common.collect.*;
import gnu.trove.set.hash.THashSet;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.support.IgnoreIndices;
@ -273,6 +271,39 @@ public class MetaData implements Iterable<IndexMetaData> {
return aliases();
}
/**
* Finds the specific index aliases that match with the specified aliases directly or partially via wildcards and
* that point to the specified concrete indices or match partially with the indices via wildcards.
*
* @param aliases The names of the index aliases to find
* @param concreteIndices The concrete indexes the index aliases must point to order to be returned.
*
* @return the found index aliases grouped by index
*/
public ImmutableMap<String, ImmutableList<AliasMetaData>> findAliases(final String[] aliases, String[] concreteIndices) {
assert aliases != null;
assert concreteIndices != null;
if (concreteIndices.length == 0) {
return ImmutableMap.of();
}
ImmutableMap.Builder<String, ImmutableList<AliasMetaData>> mapBuilder = ImmutableMap.builder();
Sets.SetView<String> intersection = Sets.intersection(Sets.newHashSet(concreteIndices), indices.keySet());
for (String index : intersection) {
IndexMetaData indexMetaData = indices.get(index);
Collection<AliasMetaData> filteredValues = Maps.filterKeys(indexMetaData.getAliases(), new Predicate<String>() {
public boolean apply(String alias) {
// Simon says: we could build and FST out of the alias key and then run a regexp query against it ;)
return Regex.simpleMatch(aliases, alias);
}
}).values();
if (!filteredValues.isEmpty()) {
mapBuilder.put(index, ImmutableList.copyOf(filteredValues));
}
}
return mapBuilder.build();
}
/**
* Returns all the concrete indices.
*/

View File

@ -0,0 +1,57 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.indices;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.rest.RestStatus;
/**
*/
public class AliasMissingException extends ElasticSearchException {
private final String[] names;
public AliasMissingException(String... names) {
super(String.format("alias [%s] missing", toNamesString(names)));
this.names = names;
}
public String[] getName() {
return names;
}
@Override
public RestStatus status() {
return RestStatus.NOT_FOUND;
}
private static String toNamesString(String... names) {
if (names == null || names.length == 0) {
return "";
} else if (names.length == 1) {
return names[0];
} else {
StringBuilder builder = new StringBuilder(names[0]);
for (int i = 1; i < names.length; i++) {
builder.append(',').append(names[i]);
}
return builder.toString();
}
}
}

View File

@ -35,6 +35,9 @@ import org.elasticsearch.rest.action.admin.cluster.shards.RestClusterSearchShard
import org.elasticsearch.rest.action.admin.cluster.state.RestClusterStateAction;
import org.elasticsearch.rest.action.admin.indices.alias.RestGetIndicesAliasesAction;
import org.elasticsearch.rest.action.admin.indices.alias.RestIndicesAliasesAction;
import org.elasticsearch.rest.action.admin.indices.alias.delete.RestIndexDeleteAliasesAction;
import org.elasticsearch.rest.action.admin.indices.alias.get.RestIndicesGetAliasesAction;
import org.elasticsearch.rest.action.admin.indices.alias.put.RestIndexPutAliasAction;
import org.elasticsearch.rest.action.admin.indices.analyze.RestAnalyzeAction;
import org.elasticsearch.rest.action.admin.indices.cache.clear.RestClearIndicesCacheAction;
import org.elasticsearch.rest.action.admin.indices.close.RestCloseIndexAction;
@ -119,6 +122,9 @@ public class RestActionModule extends AbstractModule {
bind(RestIndicesStatusAction.class).asEagerSingleton();
bind(RestIndicesSegmentsAction.class).asEagerSingleton();
bind(RestGetIndicesAliasesAction.class).asEagerSingleton();
bind(RestIndicesGetAliasesAction.class).asEagerSingleton();
bind(RestIndexDeleteAliasesAction.class).asEagerSingleton();
bind(RestIndexPutAliasAction.class).asEagerSingleton();
bind(RestIndicesAliasesAction.class).asEagerSingleton();
bind(RestCreateIndexAction.class).asEagerSingleton();
bind(RestDeleteIndexAction.class).asEagerSingleton();

View File

@ -0,0 +1,89 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.rest.action.admin.indices.alias.delete;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestXContentBuilder;
import java.io.IOException;
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
import static org.elasticsearch.rest.RestStatus.OK;
/**
*/
public class RestIndexDeleteAliasesAction extends BaseRestHandler {
@Inject
public RestIndexDeleteAliasesAction(Settings settings, Client client, RestController controller) {
super(settings, client);
controller.registerHandler(DELETE, "/{index}/_alias/{name}", this);
}
@Override
public void handleRequest(final RestRequest request, final RestChannel channel) {
final String index = request.param("index");
String alias = request.param("name");
IndicesAliasesRequest indicesAliasesRequest = new IndicesAliasesRequest();
indicesAliasesRequest.timeout(request.paramAsTime("timeout", timeValueSeconds(10)));
indicesAliasesRequest.removeAlias(index, alias);
client.admin().indices().aliases(indicesAliasesRequest, new ActionListener<IndicesAliasesResponse>() {
@Override
public void onResponse(IndicesAliasesResponse response) {
try {
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
builder.startObject();
builder.field(Fields.OK, true);
builder.field(Fields.ACK, response.isAcknowledged());
builder.endObject();
channel.sendResponse(new XContentRestResponse(request, OK, builder));
} catch (Throwable e) {
onFailure(e);
}
}
@Override
public void onFailure(Throwable e) {
try {
channel.sendResponse(new XContentThrowableRestResponse(request, e));
} catch (IOException e1) {
logger.error("Failed to send failure response", e1);
}
}
});
}
static class Fields {
static final XContentBuilderString OK = new XContentBuilderString("ok");
static final XContentBuilderString ACK = new XContentBuilderString("acknowledged");
}
}

View File

@ -0,0 +1,106 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.rest.action.admin.indices.alias.get;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesResponse;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestActions;
import org.elasticsearch.rest.action.support.RestXContentBuilder;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.rest.RestStatus.OK;
/**
*/
public class RestIndicesGetAliasesAction extends BaseRestHandler {
@Inject
public RestIndicesGetAliasesAction(Settings settings, Client client, RestController controller) {
super(settings, client);
controller.registerHandler(GET, "/_alias/{name}", this);
controller.registerHandler(GET, "/{index}/_alias/{name}", this);
}
@Override
public void handleRequest(final RestRequest request, final RestChannel channel) {
String[] aliases = request.paramAsStringArray("name", Strings.EMPTY_ARRAY);
final String[] indices = RestActions.splitIndices(request.param("index"));
IndicesGetAliasesRequest getAliasesRequest = new IndicesGetAliasesRequest(aliases);
getAliasesRequest.indices(indices);
if (request.hasParam("ignore_indices")) {
getAliasesRequest.ignoreIndices(IgnoreIndices.fromString(request.param("ignore_indices")));
}
client.admin().indices().getAliases(getAliasesRequest, new ActionListener<IndicesGetAliasesResponse>() {
@Override
public void onResponse(IndicesGetAliasesResponse response) {
try {
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
builder.startObject();
for (Map.Entry<String, List<AliasMetaData>> entry : response.getAliases().entrySet()) {
builder.startObject(entry.getKey(), XContentBuilder.FieldCaseConversion.NONE);
builder.startObject(Fields.ALIASES);
for (AliasMetaData alias : entry.getValue()) {
AliasMetaData.Builder.toXContent(alias, builder, ToXContent.EMPTY_PARAMS);
}
builder.endObject();
builder.endObject();
}
builder.endObject();
channel.sendResponse(new XContentRestResponse(request, OK, builder));
} catch (Throwable e) {
onFailure(e);
}
}
@Override
public void onFailure(Throwable e) {
try {
channel.sendResponse(new XContentThrowableRestResponse(request, e));
} catch (IOException e1) {
logger.error("Failed to send failure response", e1);
}
}
});
}
static class Fields {
static final XContentBuilderString ALIASES = new XContentBuilderString("aliases");
}
}

View File

@ -0,0 +1,159 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.rest.action.admin.indices.alias.put;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.AliasAction;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentBuilderString;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestXContentBuilder;
import java.io.IOException;
import java.util.Map;
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
import static org.elasticsearch.rest.RestRequest.Method.PUT;
import static org.elasticsearch.rest.RestStatus.OK;
/**
*/
public class RestIndexPutAliasAction extends BaseRestHandler {
@Inject
public RestIndexPutAliasAction(Settings settings, Client client, RestController controller) {
super(settings, client);
controller.registerHandler(PUT, "/{index}/_alias/{name}", this);
controller.registerHandler(PUT, "/_alias/{name}", this);
controller.registerHandler(PUT, "/{index}/_alias", this);
controller.registerHandler(PUT, "/_alias", this);
}
@Override
public void handleRequest(final RestRequest request, final RestChannel channel) {
String index = request.param("index");
String alias = request.param("name");
Map<String, Object> filter = null;
String routing = null;
String indexRouting = null;
String searchRouting = null;
if (request.hasContent()) {
XContentParser parser = null;
try {
parser = XContentFactory.xContent(request.content()).createParser(request.content());
XContentParser.Token token = parser.nextToken();
if (token == null) {
throw new ElasticSearchIllegalArgumentException("No index alias is specified");
}
String currentFieldName = null;
while ((token = parser.nextToken()) != null) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = parser.currentName();
} else if (token.isValue()) {
if ("index".equals(currentFieldName)) {
index = parser.text();
} else if ("alias".equals(currentFieldName)) {
alias = parser.text();
} else if ("routing".equals(currentFieldName)) {
routing = parser.textOrNull();
} else if ("indexRouting".equals(currentFieldName) || "index-routing".equals(currentFieldName) || "index_routing".equals(currentFieldName)) {
indexRouting = parser.textOrNull();
} else if ("searchRouting".equals(currentFieldName) || "search-routing".equals(currentFieldName) || "search_routing".equals(currentFieldName)) {
searchRouting = parser.textOrNull();
}
} else if (token == XContentParser.Token.START_OBJECT) {
if ("filter".equals(currentFieldName)) {
filter = parser.mapOrdered();
}
}
}
} catch (Throwable e) {
try {
channel.sendResponse(new XContentThrowableRestResponse(request, e));
} catch (IOException e1) {
logger.warn("Failed to send response", e1);
}
return;
} finally {
if (parser != null) {
parser.close();
}
}
}
IndicesAliasesRequest indicesAliasesRequest = new IndicesAliasesRequest();
indicesAliasesRequest.timeout(request.paramAsTime("timeout", timeValueSeconds(10)));
AliasAction aliasAction = new AliasAction(AliasAction.Type.ADD, index, alias);
indicesAliasesRequest.addAliasAction(aliasAction);
if (routing != null) {
aliasAction.routing(routing);
}
if (searchRouting != null) {
aliasAction.searchRouting(searchRouting);
}
if (indexRouting != null) {
aliasAction.indexRouting(indexRouting);
}
if (filter != null) {
aliasAction.filter(filter);
}
client.admin().indices().aliases(indicesAliasesRequest, new ActionListener<IndicesAliasesResponse>() {
@Override
public void onResponse(IndicesAliasesResponse response) {
try {
XContentBuilder builder = RestXContentBuilder.restContentBuilder(request);
builder.startObject();
builder.field(Fields.OK, true);
builder.field(Fields.ACK, response.isAcknowledged());
builder.endObject();
channel.sendResponse(new XContentRestResponse(request, OK, builder));
} catch (Throwable e) {
onFailure(e);
}
}
@Override
public void onFailure(Throwable e) {
try {
channel.sendResponse(new XContentThrowableRestResponse(request, e));
} catch (IOException e1) {
logger.error("Failed to send failure response", e1);
}
}
});
}
static class Fields {
static final XContentBuilderString OK = new XContentBuilderString("ok");
static final XContentBuilderString ACK = new XContentBuilderString("acknowledged");
}
}

View File

@ -21,11 +21,14 @@ package org.elasticsearch.test.integration.aliases;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthStatus;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.action.admin.indices.alias.get.IndicesGetAliasesResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.AliasAction;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.StopWatch;
@ -34,6 +37,7 @@ import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.FilterBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.indices.AliasMissingException;
import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.node.internal.InternalNode;
import org.elasticsearch.search.SearchHit;
@ -58,6 +62,7 @@ import static org.elasticsearch.common.settings.ImmutableSettings.settingsBuilde
import static org.elasticsearch.index.query.FilterBuilders.termFilter;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;
import static org.testng.AssertJUnit.fail;
/**
*
@ -607,6 +612,199 @@ public class IndexAliasesTests extends AbstractNodesTests {
assertThat(stopWatch.stop().lastTaskTime().millis(), lessThan(timeout.millis()));
}
@Test
public void testIndicesGetAliases() throws Exception {
// delete all indices
client1.admin().indices().prepareDelete().execute().actionGet();
Settings indexSettings = ImmutableSettings.settingsBuilder()
.put("index.number_of_shards", 1)
.put("index.number_of_replicas", 0)
.build();
logger.info("--> creating indices [foobar, test, test123, foobarbaz, bazbar]");
client1.admin().indices().prepareCreate("foobar")
.setSettings(indexSettings)
.execute().actionGet();
client1.admin().indices().prepareCreate("test")
.setSettings(indexSettings)
.execute().actionGet();
client1.admin().indices().prepareCreate("test123")
.setSettings(indexSettings)
.execute().actionGet();
client1.admin().indices().prepareCreate("foobarbaz")
.setSettings(indexSettings)
.execute().actionGet();
client1.admin().indices().prepareCreate("bazbar")
.setSettings(indexSettings)
.execute().actionGet();
logger.info("--> running cluster_health");
ClusterHealthResponse clusterHealth = client1.admin().cluster().health(clusterHealthRequest().waitForGreenStatus()).actionGet();
logger.info("--> done cluster_health, status " + clusterHealth.getStatus());
assertThat(clusterHealth.isTimedOut(), equalTo(false));
assertThat(clusterHealth.getStatus(), equalTo(ClusterHealthStatus.GREEN));
logger.info("--> creating aliases [alias1, alias2]");
client1.admin().indices().prepareAliases()
.addAlias("foobar", "alias1")
.execute().actionGet();
IndicesAliasesResponse indicesAliasesResponse = client2.admin().indices().prepareAliases()
.addAlias("foobar", "alias2")
.execute().actionGet();
assertThat(indicesAliasesResponse.isAcknowledged(), equalTo(true));
logger.info("--> getting alias1");
IndicesGetAliasesResponse response = client2.admin().indices().prepareGetAliases("alias1").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("foobar").size(), equalTo(1));
assertThat(response.getAliases().get("foobar").get(0), notNullValue());
assertThat(response.getAliases().get("foobar").get(0).alias(), equalTo("alias1"));
assertThat(response.getAliases().get("foobar").get(0).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getSearchRouting(), nullValue());
logger.info("--> getting all aliases that start with alias*");
response = client2.admin().indices().prepareGetAliases("alias*").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("foobar").size(), equalTo(2));
assertThat(response.getAliases().get("foobar").get(0), notNullValue());
assertThat(response.getAliases().get("foobar").get(0).alias(), equalTo("alias2"));
assertThat(response.getAliases().get("foobar").get(0).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getSearchRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(1), notNullValue());
assertThat(response.getAliases().get("foobar").get(1).alias(), equalTo("alias1"));
assertThat(response.getAliases().get("foobar").get(1).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(1).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(1).getSearchRouting(), nullValue());
logger.info("--> creating aliases [bar, baz, foo]");
client1.admin().indices().prepareAliases()
.addAlias("bazbar", "bar")
.addAlias("bazbar", "bac", termFilter("field", "value"))
.addAlias("foobar", "foo")
.execute().actionGet();
indicesAliasesResponse = client2.admin().indices().prepareAliases()
.addAliasAction(new AliasAction(AliasAction.Type.ADD, "foobar", "bac").routing("bla"))
.execute().actionGet();
assertThat(indicesAliasesResponse.isAcknowledged(), equalTo(true));
logger.info("--> getting bar and baz for index bazbar");
response = client2.admin().indices().prepareGetAliases("bar", "bac").addIndices("bazbar").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("bazbar").size(), equalTo(2));
assertThat(response.getAliases().get("bazbar").get(0), notNullValue());
assertThat(response.getAliases().get("bazbar").get(0).alias(), equalTo("bac"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("term"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("field"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("value"));
assertThat(response.getAliases().get("bazbar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(0).getSearchRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1), notNullValue());
assertThat(response.getAliases().get("bazbar").get(1).alias(), equalTo("bar"));
assertThat(response.getAliases().get("bazbar").get(1).getFilter(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1).getSearchRouting(), nullValue());
logger.info("--> getting *b* for index baz*");
response = client2.admin().indices().prepareGetAliases("*b*").addIndices("baz*").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("bazbar").size(), equalTo(2));
assertThat(response.getAliases().get("bazbar").get(0), notNullValue());
assertThat(response.getAliases().get("bazbar").get(0).alias(), equalTo("bac"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("term"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("field"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("value"));
assertThat(response.getAliases().get("bazbar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(0).getSearchRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1), notNullValue());
assertThat(response.getAliases().get("bazbar").get(1).alias(), equalTo("bar"));
assertThat(response.getAliases().get("bazbar").get(1).getFilter(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1).getSearchRouting(), nullValue());
logger.info("--> getting *b* for index *bar");
response = client2.admin().indices().prepareGetAliases("b*").addIndices("*bar").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(2));
assertThat(response.getAliases().get("bazbar").size(), equalTo(2));
assertThat(response.getAliases().get("bazbar").get(0), notNullValue());
assertThat(response.getAliases().get("bazbar").get(0).alias(), equalTo("bac"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("term"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("field"));
assertThat(response.getAliases().get("bazbar").get(0).getFilter().string(), containsString("value"));
assertThat(response.getAliases().get("bazbar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(0).getSearchRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1), notNullValue());
assertThat(response.getAliases().get("bazbar").get(1).alias(), equalTo("bar"));
assertThat(response.getAliases().get("bazbar").get(1).getFilter(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("bazbar").get(1).getSearchRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(0), notNullValue());
assertThat(response.getAliases().get("foobar").get(0).alias(), equalTo("bac"));
assertThat(response.getAliases().get("foobar").get(0).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getIndexRouting(), equalTo("bla"));
assertThat(response.getAliases().get("foobar").get(0).getSearchRouting(), equalTo("bla"));
logger.info("--> getting f* for index *bar");
response = client2.admin().indices().prepareGetAliases("f*").addIndices("*bar").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("foobar").get(0), notNullValue());
assertThat(response.getAliases().get("foobar").get(0).alias(), equalTo("foo"));
assertThat(response.getAliases().get("foobar").get(0).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getSearchRouting(), nullValue());
// alias at work
logger.info("--> getting f* for index *bac");
response = client2.admin().indices().prepareGetAliases("foo").addIndices("*bac").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("foobar").size(), equalTo(1));
assertThat(response.getAliases().get("foobar").get(0), notNullValue());
assertThat(response.getAliases().get("foobar").get(0).alias(), equalTo("foo"));
assertThat(response.getAliases().get("foobar").get(0).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getSearchRouting(), nullValue());
logger.info("--> getting foo for index foobar");
response = client2.admin().indices().prepareGetAliases("foo").addIndices("foobar").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(1));
assertThat(response.getAliases().get("foobar").get(0), notNullValue());
assertThat(response.getAliases().get("foobar").get(0).alias(), equalTo("foo"));
assertThat(response.getAliases().get("foobar").get(0).getFilter(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getIndexRouting(), nullValue());
assertThat(response.getAliases().get("foobar").get(0).getSearchRouting(), nullValue());
// alias at work again
logger.info("--> getting * for index *bac");
response = client2.admin().indices().prepareGetAliases("*").addIndices("*bac").execute().actionGet();
assertThat(response, notNullValue());
assertThat(response.getAliases().size(), equalTo(2));
assertThat(response.getAliases().get("foobar").size(), equalTo(4));
assertThat(response.getAliases().get("bazbar").size(), equalTo(2));
indicesAliasesResponse = client2.admin().indices().prepareAliases()
.removeAlias("foobar", "foo")
.execute().actionGet();
assertThat(indicesAliasesResponse.isAcknowledged(), equalTo(true));
try {
client2.admin().indices().prepareGetAliases("foo").addIndices("foobar").execute().actionGet();
fail("Exception should have been thrown");
} catch (AliasMissingException e) {
assertThat(e.getMessage(), equalTo("alias [foo] missing"));
}
}
private void assertHits(SearchHits hits, String... ids) {
assertThat(hits.totalHits(), equalTo((long) ids.length));
Set<String> hitIds = newHashSet();