-
Notifications
You must be signed in to change notification settings - Fork 25.5k
Add Restore Snapshot High Level REST API #32155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Restore Snapshot High Level REST API #32155
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boolean
instead? looks like it can't be null.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just a simple
if (randomBoolean()) {
restoreSnapshotRequest.waitForCompletion(true);
expectedParams....
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, that is better I think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we instead skip emitting the value if it is null?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Strings.toString
is pretty good for this. It spits it out in json.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Changed.
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class RestoreSnapshotRequestTests extends ESTestCase { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Like whether or not we support adding additional fields and reordering fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this might should also be a AbstractStreamableTestCase
as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fine by me.
|
||
RestoreSnapshotRequest restoreSnapshotRequest = new RestoreSnapshotRequest(repository, snapshot); | ||
setRandomMasterTimeout(restoreSnapshotRequest, expectedParams); | ||
Boolean waitForCompletion = randomBoolean(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
randomTimeValue()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you indent this one more level so it doesn't read like it is part of the block below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.
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