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:
parent
ff42d7cfc6
commit
cb20776439
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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+
|
||||
|
|
Loading…
Reference in New Issue