Add Restore Snapshot High Level REST API#32155
Add Restore Snapshot High Level REST API#32155danielmitterdorfer merged 5 commits intoelastic:masterfrom
Conversation
With this commit we add the restore snapshot API to the Java high level REST client. Relates elastic#27205
|
Pinging @elastic/es-core-infra |
|
|
||
| RestoreSnapshotRequest restoreSnapshotRequest = new RestoreSnapshotRequest(repository, snapshot); | ||
| setRandomMasterTimeout(restoreSnapshotRequest, expectedParams); | ||
| Boolean waitForCompletion = randomBoolean(); |
There was a problem hiding this comment.
boolean instead? looks like it can't be null.
There was a problem hiding this comment.
Why not just a simple
if (randomBoolean()) {
restoreSnapshotRequest.waitForCompletion(true);
expectedParams....
}
There was a problem hiding this comment.
Honestly, I tried to be consistent with other tests (in that case testCreateSnapshot) but I changed it now accordingly.
| CreateSnapshotResponse createSnapshotResponse = createTestSnapshot(createSnapshotRequest); | ||
| assertEquals(RestStatus.OK, createSnapshotResponse.status()); | ||
|
|
||
| RestoreSnapshotRequest request = new RestoreSnapshotRequest(testRepository, testSnapshot); |
There was a problem hiding this comment.
Delete the index and check that it came back? Stick a document in it and check that it was restored? I don't want to test snapshot/restore but I do want to get a fairly real test just in case.
There was a problem hiding this comment.
@nik9000 Do you not feel that restoring showing successful shards > 0 is enough here? Its a rest api call after all, and it might be out of scope to test this at the rest api level.
There was a problem hiding this comment.
Yeah, I suppose seeing >0 successful shards is enough. I'd still like to see that index deleted first.
There was a problem hiding this comment.
The test deletes the index now before attempting to restore it.
| if (entry.getValue() instanceof String) { | ||
| renamePattern((String) entry.getValue()); | ||
| } else { | ||
| } else if (entry.getValue() != null) { |
There was a problem hiding this comment.
Should we instead skip emitting the value if it is null?
There was a problem hiding this comment.
if im reading this right, it will only fail if its not a string and is not null. Otherwise itll emit null below in the toXContent. I think the null checks would make sense in toXContent as well, but we certainly dont want a non-string being emitted, so i think the IAE is ok here.
There was a problem hiding this comment.
@hub-cap you're reading it right. However, I decided to revert to the old behavior in this method and skip emitting renamePattern / renameReplacement now in #toXContent() when they are null.
|
|
||
| @Override | ||
| public String toString() { | ||
| return "RestoreSnapshotRequest{" + |
There was a problem hiding this comment.
Strings.toString is pretty good for this. It spits it out in json.
There was a problem hiding this comment.
Ah, good catch. I didn't know it exists. Btw, I implemented this consistently with other classes (i.e. CreateSnapshotRequest). I wonder whether we should bite the bullet and implement this consistently across all implementations of ToXContent (that also implement as of today)?
| } | ||
|
|
||
| public static RestoreSnapshotResponse fromXContent(XContentParser parser) throws IOException { | ||
| RestoreSnapshotResponse response = new RestoreSnapshotResponse(); |
There was a problem hiding this comment.
I feel like ObjectParser may be better here just so I don't have to think "does this thing really only ever spit out one fields? does this code properly ignore unknown fields so it is forward compatible?"
There was a problem hiding this comment.
We have this in another spot too, which is why i think @danielmitterdorfer wrote it this way. Its probably good to change it in both spots (CreateSnapshot). Maybe in a separate PR?
There was a problem hiding this comment.
@hub-cap correct; I implemented this identically to CreateSnapshotResponse. Similarly to RestoreInfo there is a mismatch between the object structure and the XContent structure. For RestoreInfo I managed to use ObjectParser but I had a hard time figuring out how to make it work. I also agree that if we change it here, we should change it in CreateSnapshotResponse as well.
There was a problem hiding this comment.
This definitely does not ignore unknown fields. It will fail if snapshot or accepted is not in the body. @nik9000 how should we handle this? We can go back to the older for loop style of these, or just fix it here using object parser. Id prefer the latter given @danielmitterdorfer has infinite time (which i dont know).
There was a problem hiding this comment.
Failing on less stuff is fine, but we should indeed ignore unknown fields. I think ConstructingObjectParser would work fine for this if you declare shapshot as an optionalConstructorArg and you declare accepted as boolean optionalConstructorArg and throw it on the floor when building the actual object. It isn't super efficient but it will properly handle unknown fields and it isn't too bad.
There was a problem hiding this comment.
And it means we don't need to think too hard about the parsing. Which I don't think is worth it for an API as low traffic as this.
| } | ||
|
|
||
| @Override | ||
| public String toString() { |
There was a problem hiding this comment.
Same thing about toString as above. Either way is fine with me, but we're starting to standardize on using the json.
There was a problem hiding this comment.
Thanks. Changed.
| import java.util.List; | ||
| import java.util.Map; | ||
|
|
||
| public class RestoreSnapshotRequestTests extends ESTestCase { |
There was a problem hiding this comment.
We have been using AbstractStreamableTestCase for these tests lately and I think it forces us to test important things.
There was a problem hiding this comment.
Like whether or not we support adding additional fields and reordering fields.
There was a problem hiding this comment.
I used AbstractWireSerializingTestCase as a base class because AbstractStreamableTestCase requires the test subject to be Streamable but RestoreSnapshotRequest raises an UnsupportedOperationException ("usage of Streamable is to be replaced by Writeable") in #readFrom(StreamInput).
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class RestoreSnapshotResponseTests extends AbstractXContentTestCase<RestoreSnapshotResponse> { |
There was a problem hiding this comment.
I think this might should also be a AbstractStreamableTestCase as well.
There was a problem hiding this comment.
The tests that test a class that impl fromXContent have been moving toward this. It was a newer test class created in cd3d9c9. I think its valid for this, but not valid for the request test above that only impls a toXContent
|
|
||
| RestoreSnapshotRequest restoreSnapshotRequest = new RestoreSnapshotRequest(repository, snapshot); | ||
| setRandomMasterTimeout(restoreSnapshotRequest, expectedParams); | ||
| Boolean waitForCompletion = randomBoolean(); |
There was a problem hiding this comment.
Why not just a simple
if (randomBoolean()) {
restoreSnapshotRequest.waitForCompletion(true);
expectedParams....
}
| expectedParams.put("wait_for_completion", waitForCompletion.toString()); | ||
| } | ||
| if (randomBoolean()) { | ||
| restoreSnapshotRequest.masterNodeTimeout("120s"); |
There was a problem hiding this comment.
Good idea; didn't know it existed. I changed it.
| CreateSnapshotResponse createSnapshotResponse = createTestSnapshot(createSnapshotRequest); | ||
| assertEquals(RestStatus.OK, createSnapshotResponse.status()); | ||
|
|
||
| RestoreSnapshotRequest request = new RestoreSnapshotRequest(testRepository, testSnapshot); |
There was a problem hiding this comment.
@nik9000 Do you not feel that restoring showing successful shards > 0 is enough here? Its a rest api call after all, and it might be out of scope to test this at the rest api level.
| if (entry.getValue() instanceof String) { | ||
| renamePattern((String) entry.getValue()); | ||
| } else { | ||
| } else if (entry.getValue() != null) { |
There was a problem hiding this comment.
if im reading this right, it will only fail if its not a string and is not null. Otherwise itll emit null below in the toXContent. I think the null checks would make sense in toXContent as well, but we certainly dont want a non-string being emitted, so i think the IAE is ok here.
| } | ||
|
|
||
| public static RestoreSnapshotResponse fromXContent(XContentParser parser) throws IOException { | ||
| RestoreSnapshotResponse response = new RestoreSnapshotResponse(); |
There was a problem hiding this comment.
We have this in another spot too, which is why i think @danielmitterdorfer wrote it this way. Its probably good to change it in both spots (CreateSnapshot). Maybe in a separate PR?
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public class RestoreSnapshotResponseTests extends AbstractXContentTestCase<RestoreSnapshotResponse> { |
There was a problem hiding this comment.
The tests that test a class that impl fromXContent have been moving toward this. It was a newer test class created in cd3d9c9. I think its valid for this, but not valid for the request test above that only impls a toXContent
| parser.nextToken(); // move to 'accepted' field value | ||
|
|
||
| if (parser.booleanValue()) { | ||
| // ensure accepted is a boolean value |
There was a problem hiding this comment.
I think it is weird to just drop this on the floor. But we really don't have anywhere to put it.....
There was a problem hiding this comment.
Yes, this is caused by the (already existing) impedance mismatch of XContent and object structure which honestly causes quite some headaches.
| } | ||
|
|
||
| public static RestoreSnapshotResponse fromXContent(XContentParser parser) throws IOException { | ||
| RestoreSnapshotResponse response = new RestoreSnapshotResponse(); |
There was a problem hiding this comment.
Failing on less stuff is fine, but we should indeed ignore unknown fields. I think ConstructingObjectParser would work fine for this if you declare shapshot as an optionalConstructorArg and you declare accepted as boolean optionalConstructorArg and throw it on the floor when building the actual object. It isn't super efficient but it will properly handle unknown fields and it isn't too bad.
| } | ||
|
|
||
| public static RestoreSnapshotResponse fromXContent(XContentParser parser) throws IOException { | ||
| RestoreSnapshotResponse response = new RestoreSnapshotResponse(); |
There was a problem hiding this comment.
And it means we don't need to think too hard about the parsing. Which I don't think is worth it for an API as low traffic as this.
| throw new IllegalArgumentException("unexpected token [" + parser.currentToken() + "], expected ['}']"); | ||
| } | ||
| public static final ConstructingObjectParser<RestoreSnapshotResponse, Void> PARSER = new ConstructingObjectParser<>( | ||
| "restore_snapshot", true, v -> { |
There was a problem hiding this comment.
Could you indent this one more level so it doesn't read like it is part of the block below?
|
Thanks for making all of the changes that I asked for! |
|
Thanks for your help @nik9000! |
|
Backported to 6.x in 92d7802. |
With this commit we add the restore snapshot API to the Java high level
REST client.
Relates #27205