Skip to content

Conversation

danielmitterdorfer
Copy link
Member

With this commit we add the restore snapshot API to the Java high level
REST client.

Relates #27205

With this commit we add the restore snapshot API to the Java high level
REST client.

Relates elastic#27205
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-core-infra


RestoreSnapshotRequest restoreSnapshotRequest = new RestoreSnapshotRequest(repository, snapshot);
setRandomMasterTimeout(restoreSnapshotRequest, expectedParams);
Boolean waitForCompletion = randomBoolean();
Copy link
Member

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.

Copy link
Contributor

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....
}

Copy link
Member

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.

Copy link
Member Author

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);
Copy link
Member

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.

Copy link
Contributor

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.

Copy link
Member

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.

Copy link
Member Author

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) {
Copy link
Member

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?

Copy link
Contributor

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.

Copy link
Member Author

@danielmitterdorfer danielmitterdorfer Jul 19, 2018

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{" +
Copy link
Member

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.

Copy link
Member Author

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();
Copy link
Member

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?"

Copy link
Contributor

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?

Copy link
Member Author

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.

Copy link
Contributor

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).

Copy link
Member

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.

Copy link
Member

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() {
Copy link
Member

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.

Copy link
Member Author

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 {
Copy link
Member

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.

Copy link
Member

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.

Copy link
Member Author

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> {
Copy link
Member

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.

Copy link
Contributor

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

Copy link
Member

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();
Copy link
Contributor

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");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

randomTimeValue()

Copy link
Member Author

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);
Copy link
Contributor

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) {
Copy link
Contributor

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();
Copy link
Contributor

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> {
Copy link
Contributor

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

@danielmitterdorfer
Copy link
Member Author

@hub-cap, @nik9000 thanks for your reviews! I addressed your comments now in a79f8c2. Can you please have another look?

parser.nextToken(); // move to 'accepted' field value

if (parser.booleanValue()) {
// ensure accepted is a boolean value
Copy link
Member

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.....

Copy link
Member Author

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();
Copy link
Member

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();
Copy link
Member

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.

@danielmitterdorfer
Copy link
Member Author

@hub-cap, @nik9000 with the most recent commit, RestoreSnapshotResponse supports unknown fields as well now. Can you please have another look?

Copy link
Member

@nik9000 nik9000 left a 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 -> {
Copy link
Member

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?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

@nik9000
Copy link
Member

nik9000 commented Jul 24, 2018

Thanks for making all of the changes that I asked for!

@danielmitterdorfer
Copy link
Member Author

Thanks for your help @nik9000!

@danielmitterdorfer danielmitterdorfer merged commit 73a3889 into elastic:master Jul 24, 2018
@danielmitterdorfer danielmitterdorfer deleted the client-restore-snapshot branch July 24, 2018 14:20
danielmitterdorfer added a commit that referenced this pull request Jul 26, 2018
With this commit we add the restore snapshot API to the Java high level
REST client.

Relates #27205
Relates #32155
@danielmitterdorfer
Copy link
Member Author

Backported to 6.x in 92d7802.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants