Includes the index UUID in the _cat/indices API and adds tests

for the _cat/indices functionality.

Closes #19204
Closes #19132
This commit is contained in:
Ali Beyad 2016-07-01 01:46:05 -04:00
parent ff42d7cfc6
commit cb20776439
4 changed files with 187 additions and 7 deletions

View File

@ -38,6 +38,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.Table;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
@ -84,7 +85,7 @@ public class RestIndicesAction extends AbstractCatAction {
@Override
public void processResponse(final ClusterStateResponse clusterStateResponse) {
final ClusterState state = clusterStateResponse.getState();
final String[] concreteIndices = indexNameExpressionResolver.concreteIndexNames(state, strictExpandIndicesOptions, indices);
final Index[] concreteIndices = indexNameExpressionResolver.concreteIndices(state, strictExpandIndicesOptions, indices);
// concreteIndices should contain exactly the indices in state.metaData() that were selected by clusterStateRequest using
// IndicesOptions.strictExpand(). We select the indices again here so that they can be displayed in the resulting table
// in the requesting order.
@ -129,6 +130,7 @@ public class RestIndicesAction extends AbstractCatAction {
table.addCell("health", "alias:h;desc:current health status");
table.addCell("status", "alias:s;desc:open/close status");
table.addCell("index", "alias:i,idx;desc:index name");
table.addCell("uuid", "alias:id,uuid;desc:index uuid");
table.addCell("pri", "alias:p,shards.primary,shardsPrimary;text-align:right;desc:number of primary shards");
table.addCell("rep", "alias:r,shards.replica,shardsReplica;text-align:right;desc:number of replica shards");
table.addCell("docs.count", "alias:dc,docsCount;text-align:right;desc:available docs");
@ -312,19 +314,22 @@ public class RestIndicesAction extends AbstractCatAction {
return table;
}
private Table buildTable(RestRequest request, String[] indices, ClusterHealthResponse health, IndicesStatsResponse stats, MetaData indexMetaDatas) {
// package private for testing
Table buildTable(RestRequest request, Index[] indices, ClusterHealthResponse health, IndicesStatsResponse stats, MetaData indexMetaDatas) {
Table table = getTableWithHeader(request);
for (String index : indices) {
ClusterIndexHealth indexHealth = health.getIndices().get(index);
IndexStats indexStats = stats.getIndices().get(index);
IndexMetaData indexMetaData = indexMetaDatas.getIndices().get(index);
for (final Index index : indices) {
final String indexName = index.getName();
ClusterIndexHealth indexHealth = health.getIndices().get(indexName);
IndexStats indexStats = stats.getIndices().get(indexName);
IndexMetaData indexMetaData = indexMetaDatas.getIndices().get(indexName);
IndexMetaData.State state = indexMetaData.getState();
table.startRow();
table.addCell(state == IndexMetaData.State.OPEN ? (indexHealth == null ? "red*" : indexHealth.getStatus().toString().toLowerCase(Locale.ROOT)) : null);
table.addCell(state.toString().toLowerCase(Locale.ROOT));
table.addCell(index);
table.addCell(indexName);
table.addCell(index.getUUID());
table.addCell(indexHealth == null ? null : indexHealth.getNumberOfShards());
table.addCell(indexHealth == null ? null : indexHealth.getNumberOfReplicas());
table.addCell(indexStats == null ? null : indexStats.getPrimaries().getDocs().getCount());

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices.stats;
import org.elasticsearch.action.ShardOperationFailedException;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.engine.CommitStats;
@ -26,6 +27,8 @@ import org.elasticsearch.index.engine.SegmentsStats;
import org.elasticsearch.index.translog.Translog;
import org.elasticsearch.test.ESSingleNodeTestCase;
import java.util.List;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.hasKey;
@ -108,4 +111,12 @@ public class IndicesStatsTests extends ESSingleNodeTestCase {
}
}
/**
* Gives access to package private IndicesStatsResponse constructor for test purpose.
**/
public static IndicesStatsResponse newIndicesStatsResponse(ShardStats[] shards, int totalShards, int successfulShards,
int failedShards, List<ShardOperationFailedException> shardFailures) {
return new IndicesStatsResponse(shards, totalShards, successfulShards, failedShards, shardFailures);
}
}

View File

@ -0,0 +1,162 @@
/*
* 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.rest.action.cat;
import org.elasticsearch.Version;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.indices.stats.CommonStats;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse;
import org.elasticsearch.action.admin.indices.stats.IndicesStatsTests;
import org.elasticsearch.action.admin.indices.stats.ShardStats;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.routing.ShardRouting;
import org.elasticsearch.cluster.routing.UnassignedInfo;
import org.elasticsearch.common.Table;
import org.elasticsearch.common.UUIDs;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.cache.query.QueryCacheStats;
import org.elasticsearch.index.cache.request.RequestCacheStats;
import org.elasticsearch.index.engine.SegmentsStats;
import org.elasticsearch.index.fielddata.FieldDataStats;
import org.elasticsearch.index.flush.FlushStats;
import org.elasticsearch.index.get.GetStats;
import org.elasticsearch.index.merge.MergeStats;
import org.elasticsearch.index.refresh.RefreshStats;
import org.elasticsearch.index.search.stats.SearchStats;
import org.elasticsearch.index.shard.DocsStats;
import org.elasticsearch.index.shard.IndexingStats;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.index.shard.ShardPath;
import org.elasticsearch.index.store.StoreStats;
import org.elasticsearch.index.warmer.WarmerStats;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.search.suggest.completion.CompletionStats;
import org.elasticsearch.test.ESTestCase;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyList;
import static org.hamcrest.Matchers.equalTo;
/**
* Tests for {@link RestIndicesAction}
*/
public class RestIndicesActionTests extends ESTestCase {
public void testBuildTable() {
final Settings settings = Settings.EMPTY;
final RestController restController = new RestController(settings);
final RestIndicesAction action = new RestIndicesAction(settings, restController, new IndexNameExpressionResolver(settings));
// build a (semi-)random table
final int numIndices = randomIntBetween(0, 5);
Index[] indices = new Index[numIndices];
for (int i = 0; i < numIndices; i++) {
indices[i] = new Index(randomAsciiOfLength(5), UUIDs.randomBase64UUID());
}
final MetaData.Builder metaDataBuilder = MetaData.builder();
for (final Index index : indices) {
metaDataBuilder.put(IndexMetaData.builder(index.getName())
.settings(Settings.builder()
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
.put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID()))
.creationDate(System.currentTimeMillis())
.numberOfShards(1)
.numberOfReplicas(1)
.state(IndexMetaData.State.OPEN));
}
final MetaData metaData = metaDataBuilder.build();
final ClusterState clusterState = ClusterState.builder(ClusterName.CLUSTER_NAME_SETTING.getDefault(Settings.EMPTY))
.metaData(metaData)
.build();
final String[] indicesStr = new String[indices.length];
for (int i = 0; i < indices.length; i++) {
indicesStr[i] = indices[i].getName();
}
final ClusterHealthResponse clusterHealth = new ClusterHealthResponse(
clusterState.getClusterName().value(), indicesStr, clusterState, 0, 0, 0, TimeValue.timeValueMillis(1000L)
);
final Table table = action.buildTable(null, indices, clusterHealth, randomIndicesStatsResponse(indices), metaData);
// now, verify the table is correct
int count = 0;
List<Table.Cell> headers = table.getHeaders();
assertThat(headers.get(count++).value, equalTo("health"));
assertThat(headers.get(count++).value, equalTo("status"));
assertThat(headers.get(count++).value, equalTo("index"));
assertThat(headers.get(count++).value, equalTo("uuid"));
List<List<Table.Cell>> rows = table.getRows();
assertThat(rows.size(), equalTo(indices.length));
// TODO: more to verify (e.g. randomize cluster health, num primaries, num replicas, etc)
for (int i = 0; i < rows.size(); i++) {
count = 0;
final List<Table.Cell> row = rows.get(i);
assertThat(row.get(count++).value, equalTo("red*")); // all are red because cluster state doesn't have routing entries
assertThat(row.get(count++).value, equalTo("open")); // all are OPEN for now
assertThat(row.get(count++).value, equalTo(indices[i].getName()));
assertThat(row.get(count++).value, equalTo(indices[i].getUUID()));
}
}
private IndicesStatsResponse randomIndicesStatsResponse(final Index[] indices) {
List<ShardStats> shardStats = new ArrayList<>();
for (final Index index : indices) {
for (int i = 0; i < 2; i++) {
ShardId shardId = new ShardId(index, i);
Path path = createTempDir().resolve("indices").resolve(index.getUUID()).resolve(String.valueOf(i));
ShardRouting shardRouting = ShardRouting.newUnassigned(shardId, null, i == 0,
new UnassignedInfo(UnassignedInfo.Reason.INDEX_CREATED, null));
shardRouting = shardRouting.initialize("node-0", null, ShardRouting.UNAVAILABLE_EXPECTED_SHARD_SIZE);
shardRouting = shardRouting.moveToStarted();
CommonStats stats = new CommonStats();
stats.fieldData = new FieldDataStats();
stats.queryCache = new QueryCacheStats();
stats.docs = new DocsStats();
stats.store = new StoreStats();
stats.indexing = new IndexingStats();
stats.search = new SearchStats();
stats.segments = new SegmentsStats();
stats.merge = new MergeStats();
stats.refresh = new RefreshStats();
stats.completion = new CompletionStats();
stats.requestCache = new RequestCacheStats();
stats.get = new GetStats();
stats.flush = new FlushStats();
stats.warmer = new WarmerStats();
shardStats.add(new ShardStats(shardRouting, new ShardPath(false, path, path, shardId), stats, null));
}
}
return IndicesStatsTests.newIndicesStatsResponse(
shardStats.toArray(new ShardStats[shardStats.size()]), shardStats.size(), shardStats.size(), 0, emptyList()
);
}
}

View File

@ -26,6 +26,7 @@
/^(green \s+
open \s+
index1 \s+
([a-zA-Z0-9=/_+]|[\\\-]){22} \s+
1 \s+
0 \s+
0 \s+
@ -62,6 +63,7 @@
/^( \s+
close \s+
index1 \s+
([a-zA-Z0-9=/_+]|[\\\-]){22} \s+
\s+
\s+
\s+