Adds ignoreUnavailable option to the snapshot status API (#20066)
Adds ignoreUnavailable to the snapshot status API to be consistent with the get snapshots API which has a similar parameter. If ignoreUnavailable is set to true, then the snapshot status request will ignore any snapshots that were not found in the repository, instead of throwing a SnapshotMissingException. Closes #18522
This commit is contained in:
parent
cf32f8de34
commit
1c9b64e09a
|
@ -38,6 +38,8 @@ public class SnapshotsStatusRequest extends MasterNodeRequest<SnapshotsStatusReq
|
|||
|
||||
private String[] snapshots = Strings.EMPTY_ARRAY;
|
||||
|
||||
private boolean ignoreUnavailable;
|
||||
|
||||
public SnapshotsStatusRequest() {
|
||||
}
|
||||
|
||||
|
@ -112,11 +114,33 @@ public class SnapshotsStatusRequest extends MasterNodeRequest<SnapshotsStatusReq
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to <code>true</code> to ignore unavailable snapshots, instead of throwing an exception.
|
||||
* Defaults to <code>false</code>, which means unavailable snapshots cause an exception to be thrown.
|
||||
*
|
||||
* @param ignoreUnavailable whether to ignore unavailable snapshots
|
||||
* @return this request
|
||||
*/
|
||||
public SnapshotsStatusRequest ignoreUnavailable(boolean ignoreUnavailable) {
|
||||
this.ignoreUnavailable = ignoreUnavailable;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the request permits unavailable snapshots to be ignored.
|
||||
*
|
||||
* @return true if the request will ignore unavailable snapshots, false if it will throw an exception on unavailable snapshots
|
||||
*/
|
||||
public boolean ignoreUnavailable() {
|
||||
return ignoreUnavailable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readFrom(StreamInput in) throws IOException {
|
||||
super.readFrom(in);
|
||||
repository = in.readString();
|
||||
snapshots = in.readStringArray();
|
||||
ignoreUnavailable = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -124,5 +148,6 @@ public class SnapshotsStatusRequest extends MasterNodeRequest<SnapshotsStatusReq
|
|||
super.writeTo(out);
|
||||
out.writeString(repository);
|
||||
out.writeStringArray(snapshots);
|
||||
out.writeBoolean(ignoreUnavailable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,4 +74,16 @@ public class SnapshotsStatusRequestBuilder extends MasterNodeOperationRequestBui
|
|||
request.snapshots(ArrayUtils.concat(request.snapshots(), snapshots));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to <code>true</code> to ignore unavailable snapshots, instead of throwing an exception.
|
||||
* Defaults to <code>false</code>, which means unavailable snapshots cause an exception to be thrown.
|
||||
*
|
||||
* @param ignoreUnavailable whether to ignore unavailable snapshots.
|
||||
* @return this builder
|
||||
*/
|
||||
public SnapshotsStatusRequestBuilder setIgnoreUnavailable(boolean ignoreUnavailable) {
|
||||
request.ignoreUnavailable(ignoreUnavailable);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,7 +214,14 @@ public class TransportSnapshotsStatusAction extends TransportMasterNodeAction<Sn
|
|||
SnapshotId snapshotId = matchedSnapshotIds.get(snapshotName);
|
||||
if (snapshotId == null) {
|
||||
// neither in the current snapshot entries nor found in the repository
|
||||
throw new SnapshotMissingException(repositoryName, snapshotName);
|
||||
if (request.ignoreUnavailable()) {
|
||||
// ignoring unavailable snapshots, so skip over
|
||||
logger.debug("snapshot status request ignoring snapshot [{}], not found in repository [{}]",
|
||||
snapshotName, repositoryName);
|
||||
continue;
|
||||
} else {
|
||||
throw new SnapshotMissingException(repositoryName, snapshotName);
|
||||
}
|
||||
}
|
||||
SnapshotInfo snapshotInfo = snapshotsService.snapshot(repositoryName, snapshotId);
|
||||
List<SnapshotIndexShardStatus> shardStatusBuilder = new ArrayList<>();
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
package org.elasticsearch.rest.action.admin.cluster;
|
||||
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusRequest;
|
||||
import org.elasticsearch.action.admin.cluster.snapshots.status.SnapshotsStatusResponse;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
|
@ -54,9 +53,10 @@ public class RestSnapshotsStatusAction extends BaseRestHandler {
|
|||
if (snapshots.length == 1 && "_all".equalsIgnoreCase(snapshots[0])) {
|
||||
snapshots = Strings.EMPTY_ARRAY;
|
||||
}
|
||||
SnapshotsStatusRequest snapshotsStatusResponse = snapshotsStatusRequest(repository).snapshots(snapshots);
|
||||
SnapshotsStatusRequest snapshotsStatusRequest = snapshotsStatusRequest(repository).snapshots(snapshots);
|
||||
snapshotsStatusRequest.ignoreUnavailable(request.paramAsBoolean("ignore_unavailable", snapshotsStatusRequest.ignoreUnavailable()));
|
||||
|
||||
snapshotsStatusResponse.masterNodeTimeout(request.paramAsTime("master_timeout", snapshotsStatusResponse.masterNodeTimeout()));
|
||||
client.admin().cluster().snapshotsStatus(snapshotsStatusResponse, new RestToXContentListener<SnapshotsStatusResponse>(channel));
|
||||
snapshotsStatusRequest.masterNodeTimeout(request.paramAsTime("master_timeout", snapshotsStatusRequest.masterNodeTimeout()));
|
||||
client.admin().cluster().snapshotsStatus(snapshotsStatusRequest, new RestToXContentListener<>(channel));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,15 +30,15 @@ import java.io.IOException;
|
|||
public class SnapshotMissingException extends SnapshotException {
|
||||
|
||||
public SnapshotMissingException(final String repositoryName, final SnapshotId snapshotId, final Throwable cause) {
|
||||
super(repositoryName, snapshotId, "is missing", cause);
|
||||
super(repositoryName, snapshotId, " is missing", cause);
|
||||
}
|
||||
|
||||
public SnapshotMissingException(final String repositoryName, final SnapshotId snapshotId) {
|
||||
super(repositoryName, snapshotId, "is missing");
|
||||
super(repositoryName, snapshotId, " is missing");
|
||||
}
|
||||
|
||||
public SnapshotMissingException(final String repositoryName, final String snapshotName) {
|
||||
super(repositoryName, snapshotName, "is missing");
|
||||
super(repositoryName, snapshotName, " is missing");
|
||||
}
|
||||
|
||||
public SnapshotMissingException(StreamInput in) throws IOException {
|
||||
|
|
|
@ -1504,12 +1504,24 @@ public class SharedClusterSnapshotRestoreIT extends AbstractSnapshotIntegTestCas
|
|||
logger.info("--> checking that _current no longer returns the snapshot");
|
||||
assertThat(client.admin().cluster().prepareGetSnapshots("test-repo").addSnapshots("_current").execute().actionGet().getSnapshots().isEmpty(), equalTo(true));
|
||||
|
||||
try {
|
||||
client.admin().cluster().prepareSnapshotStatus("test-repo").addSnapshots("test-snap-doesnt-exist").execute().actionGet();
|
||||
fail();
|
||||
} catch (SnapshotMissingException ex) {
|
||||
// Expected
|
||||
}
|
||||
// test that getting an unavailable snapshot status throws an exception if ignoreUnavailable is false on the request
|
||||
SnapshotMissingException ex = expectThrows(SnapshotMissingException.class, () ->
|
||||
client.admin().cluster().prepareSnapshotStatus("test-repo").addSnapshots("test-snap-doesnt-exist").get());
|
||||
assertEquals("[test-repo:test-snap-doesnt-exist] is missing", ex.getMessage());
|
||||
// test that getting an unavailable snapshot status does not throw an exception if ignoreUnavailable is true on the request
|
||||
response = client.admin().cluster().prepareSnapshotStatus("test-repo")
|
||||
.addSnapshots("test-snap-doesnt-exist")
|
||||
.setIgnoreUnavailable(true)
|
||||
.get();
|
||||
assertTrue(response.getSnapshots().isEmpty());
|
||||
// test getting snapshot status for available and unavailable snapshots where ignoreUnavailable is true
|
||||
// (available one should be returned)
|
||||
response = client.admin().cluster().prepareSnapshotStatus("test-repo")
|
||||
.addSnapshots("test-snap", "test-snap-doesnt-exist")
|
||||
.setIgnoreUnavailable(true)
|
||||
.get();
|
||||
assertEquals(1, response.getSnapshots().size());
|
||||
assertEquals("test-snap", response.getSnapshots().get(0).getSnapshot().getSnapshotId().getName());
|
||||
}
|
||||
|
||||
public void testSnapshotRelocatingPrimary() throws Exception {
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
"master_timeout": {
|
||||
"type" : "time",
|
||||
"description" : "Explicit operation timeout for connection to master node"
|
||||
},
|
||||
"ignore_unavailable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore unavailable snapshots, defaults to false which means a SnapshotMissingException is thrown"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -19,9 +19,13 @@
|
|||
"master_timeout": {
|
||||
"type" : "time",
|
||||
"description" : "Explicit operation timeout for connection to master node"
|
||||
},
|
||||
"ignore_unavailable": {
|
||||
"type": "boolean",
|
||||
"description": "Whether to ignore unavailable snapshots, defaults to false which means a SnapshotMissingException is thrown"
|
||||
}
|
||||
}
|
||||
},
|
||||
"body": null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
setup:
|
||||
|
||||
- do:
|
||||
snapshot.create_repository:
|
||||
repository: test_repo_get_1
|
||||
body:
|
||||
type: fs
|
||||
settings:
|
||||
location: "test_repo_get_1_loc"
|
||||
|
||||
---
|
||||
teardown:
|
||||
|
||||
- do:
|
||||
snapshot.delete_repository:
|
||||
repository: test_repo_get_1
|
||||
|
||||
---
|
||||
"Get snapshot info":
|
||||
|
||||
- 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
|
||||
wait_for_completion: true
|
||||
|
||||
- do:
|
||||
snapshot.get:
|
||||
repository: test_repo_get_1
|
||||
snapshot: test_snapshot
|
||||
|
||||
- is_true: snapshots
|
||||
|
||||
---
|
||||
"Get missing snapshot info throws an exception":
|
||||
|
||||
- do:
|
||||
catch: /snapshot_missing_exception.+ is missing/
|
||||
snapshot.get:
|
||||
repository: test_repo_get_1
|
||||
snapshot: test_nonexistent_snapshot
|
||||
|
||||
---
|
||||
"Get missing snapshot info succeeds when ignoreUnavailable is true":
|
||||
|
||||
- do:
|
||||
snapshot.get:
|
||||
repository: test_repo_get_1
|
||||
snapshot: test_nonexistent_snapshot
|
||||
ignore_unavailable: true
|
||||
|
||||
- is_true: snapshots
|
|
@ -0,0 +1,61 @@
|
|||
---
|
||||
setup:
|
||||
|
||||
- do:
|
||||
snapshot.create_repository:
|
||||
repository: test_repo_status_1
|
||||
body:
|
||||
type: fs
|
||||
settings:
|
||||
location: "test_repo_status_1_loc"
|
||||
|
||||
---
|
||||
teardown:
|
||||
|
||||
- do:
|
||||
snapshot.delete_repository:
|
||||
repository: test_repo_status_1
|
||||
|
||||
---
|
||||
"Get snapshot status":
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: test_index
|
||||
body:
|
||||
settings:
|
||||
number_of_shards: 1
|
||||
number_of_replicas: 0
|
||||
|
||||
- do:
|
||||
snapshot.create:
|
||||
repository: test_repo_status_1
|
||||
snapshot: test_snapshot
|
||||
wait_for_completion: true
|
||||
|
||||
- do:
|
||||
snapshot.status:
|
||||
repository: test_repo_status_1
|
||||
snapshot: test_snapshot
|
||||
|
||||
- is_true: snapshots
|
||||
|
||||
---
|
||||
"Get missing snapshot status throws an exception":
|
||||
|
||||
- do:
|
||||
catch: /snapshot_missing_exception.+ is missing/
|
||||
snapshot.status:
|
||||
repository: test_repo_status_1
|
||||
snapshot: test_nonexistent_snapshot
|
||||
|
||||
---
|
||||
"Get missing snapshot status succeeds when ignoreUnavailable is true":
|
||||
|
||||
- do:
|
||||
snapshot.status:
|
||||
repository: test_repo_status_1
|
||||
snapshot: test_nonexistent_snapshot
|
||||
ignore_unavailable: true
|
||||
|
||||
- is_true: snapshots
|
Loading…
Reference in New Issue