Skip to content

Commit

Permalink
Add parameter to exclude indices in a snapshot from response (#86269)
Browse files Browse the repository at this point in the history
Adds a parameter `index_names` to the get snapshots API so that users may exclude the potentially very long index name lists when listing out snapshots.

closes #82937
  • Loading branch information
original-brownbear authored Apr 29, 2022
1 parent c49b92e commit b323e8e
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 27 deletions.
6 changes: 6 additions & 0 deletions docs/changelog/86269.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
pr: 86269
summary: Add parameter to exclude indices in a snapshot from response
area: Snapshot/Restore
type: enhancement
issues:
- 82937
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ version of Elasticsearch which took the snapshot, the start and end times of
the snapshot, and the number of shards snapshotted. Defaults to `true`. If
`false`, omits the additional information.

`index_names`::
(Optional, Boolean)
If `true`, returns the list of index names included in each snapshot in the response.
Defaults to `true`.

`index_details`::
(Optional, Boolean)
If `true`, returns additional information about each index in the snapshot
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,40 +90,45 @@ public void testSortOrder() throws Exception {
}

private void doTestSortOrder(String repoName, Collection<String> allSnapshotNames, SortOrder order) throws IOException {
final List<SnapshotInfo> defaultSorting = clusterAdmin().prepareGetSnapshots(repoName).setOrder(order).get().getSnapshots();
final boolean includeIndexNames = randomBoolean();
final List<SnapshotInfo> defaultSorting = clusterAdmin().prepareGetSnapshots(repoName)
.setOrder(order)
.setIncludeIndexNames(includeIndexNames)
.get()
.getSnapshots();
assertSnapshotListSorted(defaultSorting, null, order);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.NAME, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.NAME, order, includeIndexNames),
GetSnapshotsRequest.SortBy.NAME,
order
);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.DURATION, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.DURATION, order, includeIndexNames),
GetSnapshotsRequest.SortBy.DURATION,
order
);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.INDICES, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.INDICES, order, includeIndexNames),
GetSnapshotsRequest.SortBy.INDICES,
order
);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.START_TIME, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.START_TIME, order, includeIndexNames),
GetSnapshotsRequest.SortBy.START_TIME,
order
);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.SHARDS, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.SHARDS, order, includeIndexNames),
GetSnapshotsRequest.SortBy.SHARDS,
order
);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.FAILED_SHARDS, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.FAILED_SHARDS, order, includeIndexNames),
GetSnapshotsRequest.SortBy.FAILED_SHARDS,
order
);
assertSnapshotListSorted(
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.REPOSITORY, order),
allSnapshotsSorted(allSnapshotNames, repoName, GetSnapshotsRequest.SortBy.REPOSITORY, order, includeIndexNames),
GetSnapshotsRequest.SortBy.REPOSITORY,
order
);
Expand All @@ -143,26 +148,35 @@ public void testResponseSizeLimit() throws Exception {

private void doTestPagination(String repoName, List<String> names, GetSnapshotsRequest.SortBy sort, SortOrder order)
throws IOException {
final List<SnapshotInfo> allSnapshotsSorted = allSnapshotsSorted(names, repoName, sort, order);
final GetSnapshotsResponse batch1 = sortedWithLimit(repoName, sort, null, 2, order);
final boolean includeIndexNames = randomBoolean();
final List<SnapshotInfo> allSnapshotsSorted = allSnapshotsSorted(names, repoName, sort, order, includeIndexNames);
final GetSnapshotsResponse batch1 = sortedWithLimit(repoName, sort, null, 2, order, includeIndexNames);
assertEquals(allSnapshotsSorted.subList(0, 2), batch1.getSnapshots());
final GetSnapshotsResponse batch2 = sortedWithLimit(repoName, sort, batch1.next(), 2, order);
final GetSnapshotsResponse batch2 = sortedWithLimit(repoName, sort, batch1.next(), 2, order, includeIndexNames);
assertEquals(allSnapshotsSorted.subList(2, 4), batch2.getSnapshots());
final int lastBatch = names.size() - batch1.getSnapshots().size() - batch2.getSnapshots().size();
final GetSnapshotsResponse batch3 = sortedWithLimit(repoName, sort, batch2.next(), lastBatch, order);
final GetSnapshotsResponse batch3 = sortedWithLimit(repoName, sort, batch2.next(), lastBatch, order, includeIndexNames);
assertEquals(
batch3.getSnapshots(),
allSnapshotsSorted.subList(batch1.getSnapshots().size() + batch2.getSnapshots().size(), names.size())
);
final GetSnapshotsResponse batch3NoLimit = sortedWithLimit(repoName, sort, batch2.next(), GetSnapshotsRequest.NO_LIMIT, order);
final GetSnapshotsResponse batch3NoLimit = sortedWithLimit(
repoName,
sort,
batch2.next(),
GetSnapshotsRequest.NO_LIMIT,
order,
includeIndexNames
);
assertNull(batch3NoLimit.next());
assertEquals(batch3.getSnapshots(), batch3NoLimit.getSnapshots());
final GetSnapshotsResponse batch3LargeLimit = sortedWithLimit(
repoName,
sort,
batch2.next(),
lastBatch + randomIntBetween(1, 100),
order
order,
includeIndexNames
);
assertEquals(batch3.getSnapshots(), batch3LargeLimit.getSnapshots());
assertNull(batch3LargeLimit.next());
Expand Down Expand Up @@ -356,10 +370,11 @@ private void createIndexWithContent(String indexName) {
private static void assertStablePagination(String repoName, Collection<String> allSnapshotNames, GetSnapshotsRequest.SortBy sort)
throws IOException {
final SortOrder order = randomFrom(SortOrder.values());
final List<SnapshotInfo> allSorted = allSnapshotsSorted(allSnapshotNames, repoName, sort, order);
final boolean includeIndexNames = sort == GetSnapshotsRequest.SortBy.INDICES || randomBoolean();
final List<SnapshotInfo> allSorted = allSnapshotsSorted(allSnapshotNames, repoName, sort, order, includeIndexNames);

for (int i = 1; i <= allSnapshotNames.size(); i++) {
final List<SnapshotInfo> subsetSorted = sortedWithLimit(repoName, sort, null, i, order).getSnapshots();
final List<SnapshotInfo> subsetSorted = sortedWithLimit(repoName, sort, null, i, order, includeIndexNames).getSnapshots();
assertEquals(subsetSorted, allSorted.subList(0, i));
}

Expand All @@ -371,9 +386,17 @@ private static void assertStablePagination(String repoName, Collection<String> a
sort,
GetSnapshotsRequest.After.from(after, sort).asQueryParam(),
i,
order
order,
includeIndexNames
);
final GetSnapshotsResponse getSnapshotsResponseNumeric = sortedWithLimit(
repoName,
sort,
j + 1,
i,
order,
includeIndexNames
);
final GetSnapshotsResponse getSnapshotsResponseNumeric = sortedWithLimit(repoName, sort, j + 1, i, order);
final List<SnapshotInfo> subsetSorted = getSnapshotsResponse.getSnapshots();
assertEquals(subsetSorted, getSnapshotsResponseNumeric.getSnapshots());
assertEquals(subsetSorted, allSorted.subList(j + 1, j + i + 1));
Expand All @@ -389,15 +412,22 @@ private static List<SnapshotInfo> allSnapshotsSorted(
Collection<String> allSnapshotNames,
String repoName,
GetSnapshotsRequest.SortBy sortBy,
SortOrder order
SortOrder order,
boolean includeIndices
) throws IOException {
final Request request = baseGetSnapshotsRequest(repoName);
request.addParameter("sort", sortBy.toString());
if (order == SortOrder.DESC || randomBoolean()) {
request.addParameter("order", order.toString());
}
addIndexNamesParameter(includeIndices, request);
final GetSnapshotsResponse getSnapshotsResponse = readSnapshotInfos(getRestClient().performRequest(request));
final List<SnapshotInfo> snapshotInfos = getSnapshotsResponse.getSnapshots();
if (includeIndices == false) {
for (SnapshotInfo snapshotInfo : snapshotInfos) {
assertThat(snapshotInfo.indices(), empty());
}
}
assertEquals(snapshotInfos.size(), allSnapshotNames.size());
assertEquals(getSnapshotsResponse.totalCount(), allSnapshotNames.size());
assertEquals(0, getSnapshotsResponse.remaining());
Expand Down Expand Up @@ -429,7 +459,8 @@ private static GetSnapshotsResponse sortedWithLimit(
GetSnapshotsRequest.SortBy sortBy,
String after,
int size,
SortOrder order
SortOrder order,
boolean includeIndices
) throws IOException {
final Request request = baseGetSnapshotsRequest(repoName);
request.addParameter("sort", sortBy.toString());
Expand All @@ -442,16 +473,26 @@ private static GetSnapshotsResponse sortedWithLimit(
if (order == SortOrder.DESC || randomBoolean()) {
request.addParameter("order", order.toString());
}
addIndexNamesParameter(includeIndices, request);
final Response response = getRestClient().performRequest(request);
return readSnapshotInfos(response);
}

private static void addIndexNamesParameter(boolean includeIndices, Request request) {
if (includeIndices == false) {
request.addParameter(SnapshotInfo.INDEX_NAMES_XCONTENT_PARAM, "false");
} else if (randomBoolean()) {
request.addParameter(SnapshotInfo.INDEX_NAMES_XCONTENT_PARAM, "true");
}
}

private static GetSnapshotsResponse sortedWithLimit(
String repoName,
GetSnapshotsRequest.SortBy sortBy,
int offset,
int size,
SortOrder order
SortOrder order,
boolean includeIndices
) throws IOException {
final Request request = baseGetSnapshotsRequest(repoName);
request.addParameter("sort", sortBy.toString());
Expand All @@ -462,6 +503,7 @@ private static GetSnapshotsResponse sortedWithLimit(
if (order == SortOrder.DESC || randomBoolean()) {
request.addParameter("order", order.toString());
}
addIndexNamesParameter(includeIndices, request);
final Response response = getRestClient().performRequest(request);
return readSnapshotInfos(response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@
"type":"boolean",
"description":"Whether to ignore unavailable snapshots, defaults to false which means a SnapshotMissingException is thrown"
},
"index_names":{
"type":"boolean",
"description":"Whether to include the name of each index in the snapshot. Defaults to true."
},
"index_details":{
"type":"boolean",
"description":"Whether to include details of each index in the snapshot, if those details are available. Defaults to false."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,43 @@ setup:
repository: test_repo_get_1
snapshot: test_snapshot_with_index_details

---
"Get snapshot info without index names":
- skip:
version: " - 8.2.99"
reason: "Introduced in 8.3.0"

- do:
indices.create:
index: test_index
body:
settings:
number_of_shards: 1
number_of_replicas: 0

- do:
snapshot.create:
repository: test_repo_get_1
snapshot: test_snapshot_without_index_names
wait_for_completion: true

- do:
snapshot.get:
repository: test_repo_get_1
snapshot: test_snapshot_without_index_names
index_names: false
human: true

- is_true: snapshots
- match: { snapshots.0.snapshot: test_snapshot_without_index_names }
- match: { snapshots.0.state: SUCCESS }
- is_false: snapshots.0.indices

- do:
snapshot.delete:
repository: test_repo_get_1
snapshot: test_snapshot_without_index_names

---
"Get snapshot info without repository names":

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ public class GetSnapshotsRequest extends MasterNodeRequest<GetSnapshotsRequest>

private static final Version SORT_BY_SHARDS_OR_REPO_VERSION = Version.V_7_16_0;

private static final Version INDICES_FLAG_VERSION = Version.V_8_3_0;

public static final int NO_LIMIT = -1;

/**
Expand Down Expand Up @@ -84,6 +86,8 @@ public class GetSnapshotsRequest extends MasterNodeRequest<GetSnapshotsRequest>

private boolean verbose = DEFAULT_VERBOSE_MODE;

private boolean includeIndexNames = true;

public GetSnapshotsRequest() {}

/**
Expand Down Expand Up @@ -130,6 +134,9 @@ public GetSnapshotsRequest(StreamInput in) throws IOException {
if (in.getVersion().onOrAfter(FROM_SORT_VALUE_VERSION)) {
fromSortValue = in.readOptionalString();
}
if (in.getVersion().onOrAfter(INDICES_FLAG_VERSION)) {
includeIndexNames = in.readBoolean();
}
}
}

Expand Down Expand Up @@ -184,6 +191,9 @@ public void writeTo(StreamOutput out) throws IOException {
} else if (fromSortValue != null) {
throw new IllegalArgumentException("can't use after-value in snapshot request with node version [" + out.getVersion() + "]");
}
if (out.getVersion().onOrAfter(INDICES_FLAG_VERSION)) {
out.writeBoolean(includeIndexNames);
}
}

@Override
Expand Down Expand Up @@ -324,6 +334,15 @@ public GetSnapshotsRequest verbose(boolean verbose) {
return this;
}

public GetSnapshotsRequest includeIndexNames(boolean indices) {
this.includeIndexNames = indices;
return this;
}

public boolean includeIndexNames() {
return includeIndexNames;
}

public After after() {
return after;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,10 @@ public GetSnapshotsRequestBuilder setOrder(SortOrder order) {
return this;
}

public GetSnapshotsRequestBuilder setIncludeIndexNames(boolean indices) {
request.includeIndexNames(indices);
return this;

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ protected void masterOperation(
request.size(),
request.order(),
SnapshotPredicates.fromRequest(request),
request.includeIndexNames(),
listener
);
}
Expand Down Expand Up @@ -166,6 +167,7 @@ private void getMultipleReposSnapshotInfo(
int size,
SortOrder order,
SnapshotPredicates predicates,
boolean indices,
ActionListener<GetSnapshotsResponse> listener
) {
// short-circuit if there are no repos, because we can not create GroupedActionListener of size 0
Expand Down Expand Up @@ -193,7 +195,7 @@ private void getMultipleReposSnapshotInfo(
.mapToInt(s -> s.remaining)
.sum();
return new GetSnapshotsResponse(
snapshotInfos,
indices ? snapshotInfos : snapshotInfos.stream().map(SnapshotInfo::withoutIndices).toList(),
failures,
remaining > 0
? GetSnapshotsRequest.After.from(snapshotInfos.get(snapshotInfos.size() - 1), sortBy).asQueryParam()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static org.elasticsearch.rest.RestRequest.Method.GET;
import static org.elasticsearch.snapshots.SnapshotInfo.INCLUDE_REPOSITORY_XCONTENT_PARAM;
import static org.elasticsearch.snapshots.SnapshotInfo.INDEX_DETAILS_XCONTENT_PARAM;
import static org.elasticsearch.snapshots.SnapshotInfo.INDEX_NAMES_XCONTENT_PARAM;

/**
* Returns information about snapshot
Expand All @@ -50,7 +51,7 @@ public String getName() {

@Override
protected Set<String> responseParams() {
return Set.of(INDEX_DETAILS_XCONTENT_PARAM, INCLUDE_REPOSITORY_XCONTENT_PARAM);
return Set.of(INDEX_DETAILS_XCONTENT_PARAM, INCLUDE_REPOSITORY_XCONTENT_PARAM, INDEX_NAMES_XCONTENT_PARAM);
}

@Override
Expand Down Expand Up @@ -80,6 +81,7 @@ public RestChannelConsumer prepareRequest(final RestRequest request, final NodeC

final SortOrder order = SortOrder.fromString(request.param("order", getSnapshotsRequest.order().toString()));
getSnapshotsRequest.order(order);
getSnapshotsRequest.includeIndexNames(request.paramAsBoolean(INDEX_NAMES_XCONTENT_PARAM, getSnapshotsRequest.includeIndexNames()));
getSnapshotsRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getSnapshotsRequest.masterNodeTimeout()));
return channel -> new RestCancellableNodeClient(client, request.getHttpChannel()).admin()
.cluster()
Expand Down
Loading

0 comments on commit b323e8e

Please sign in to comment.