-
Notifications
You must be signed in to change notification settings - Fork 25k
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
HLRC: migration api - upgrade #34898
HLRC: migration api - upgrade #34898
Conversation
Pinging @elastic/es-core-infra |
a7f9368
to
826c19e
Compare
BulkByScrollResponse::fromXContent, Collections.emptySet()); | ||
} | ||
|
||
public IndexUpgradeSubmissionResponse submitUpgradeTask(IndexUpgradeRequest request, RequestOptions options) throws IOException { |
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.
as discussed, I want to refactor that later to return TaskSubmissionResponse and use across other methods where wait_for_completion=false was used
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.
++.
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.
there is another PR where we discussed if it wouldn't be better to return just TaskID:
https://github.com/elastic/elasticsearch/pull/35202/files
I might get back to this one and refactor to this TaskID
@@ -80,4 +92,72 @@ public void testGetAssistance() throws IOException { | |||
} | |||
// end::get-assistance-response | |||
} | |||
|
|||
public void testUpgrade() throws IOException { |
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.
here I am adding these test cases which are duplicates of the one I have in MigrationIT. I made it more documentation friendly here though.
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.
++
import java.util.Arrays; | ||
import java.util.Objects; | ||
|
||
public class IndexUpgradeRequest extends MasterNodeReadRequest<IndexUpgradeRequest> implements IndicesRequest { |
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 request allows only one index to be used - as per rest spec - however the interface returns arrays. might be a bit confusing..
indices = new String[]{index}; | ||
} | ||
|
||
public IndexUpgradeRequest(StreamInput in) throws IOException { |
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.
to be safe, I was looking into how IndexUpgradeInfo was implemented, copied that class and removed some methods that were not needed. Not sure if we really need this constructor. This is probably how this could be used on the server side, but that class is intended to be used on client side only. Should I remove it too?
/** | ||
* Response object that contains the taskID from submitted IndexUpgradeRequest | ||
*/ | ||
public class IndexUpgradeSubmissionResponse extends ActionResponse implements ToXContentObject { |
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.
as mentioned earlier - this will be refactored later
@hub-cap would you like to have a look into this one? |
Implement high level client for migration upgrade API. It should wrap RestHighLevelClient and expose high level IndexUpgradeRequest (new), IndexTaskResponse for submissions with wait_for_completion=false and BulkByScrollResponse (already used) objects. refers: elastic#29827
ef85460
to
a47e432
Compare
return putParam("wait_for_completion", Boolean.TRUE.toString()); | ||
} | ||
return this; | ||
return putParam("wait_for_completion", Boolean.toString(waitForCompletion)); |
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.
that need to be to set false and pass through to the server.
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.
Ahh, this is due to the fact that wait_for_completion
defaults to true in this API, right?
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.
exactly. See RestIndexUpgradeAction:60
if (request.paramAsBoolean("wait_for_completion", true)) {
@@ -0,0 +1,79 @@ | |||
[[java-rest-high-migration-upgrade]] |
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.
there is a lot of duplication between this and for instance bulk api doc. Probably some refactoring to remove doc duplication would be welcome
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.
yea i think that we can wait till docs squares away what they are doing with our rest api docs before diving in to 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.
ok
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.
Great work, getting close to finishing this! Thanks for all the thought around the task work too. Some nits mostly and the test comment below.
Please have a look at the test cases that recent HLRC APIs have done for the response objects. Lets add one for the submission response.
BulkByScrollResponse::fromXContent, Collections.emptySet()); | ||
} | ||
|
||
public IndexUpgradeSubmissionResponse submitUpgradeTask(IndexUpgradeRequest request, RequestOptions options) throws IOException { |
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.
++.
return putParam("wait_for_completion", Boolean.TRUE.toString()); | ||
} | ||
return this; | ||
return putParam("wait_for_completion", Boolean.toString(waitForCompletion)); |
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.
Ahh, this is due to the fact that wait_for_completion
defaults to true in this API, right?
import java.util.Arrays; | ||
import java.util.Objects; | ||
|
||
public class IndexUpgradeRequest extends MasterNodeReadRequest<IndexUpgradeRequest> implements IndicesRequest { |
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.
some javadoc here pls
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.
done
this.task = task; | ||
} | ||
|
||
|
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.
remove a space
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.
++
} | ||
|
||
@Override | ||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { |
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 can remove 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.
++
new IndexUpgradeInfoRequest("test"), RequestOptions.DEFAULT); | ||
assertEquals(0, response.getActions().size()); | ||
} | ||
} | ||
|
||
public void testUpgrade() throws IOException { |
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 seems like a failure case in the test itself but the name of the method does not seem to reflect that. Something like testUpgradeIndexCannotBeUpgraded
(feel free to name it yourself, im not a stickler on names).
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. Sadly this is not possible to test easily the real upgrade
private BooleanSupplier checkCompletionStatus(IndexUpgradeSubmissionResponse upgrade) { | ||
return () -> { | ||
try { | ||
Response response = client().performRequest(new Request("GET", "/_tasks/" + upgrade.getTask().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.
pls put a note saying why this is low level rest (the tasks api has not been finished yet etc).
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.
will do- will leave a TODO note to revisit once the high level api for getTaskByID is finished
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.
<3
@@ -80,4 +92,72 @@ public void testGetAssistance() throws IOException { | |||
} | |||
// end::get-assistance-response | |||
} | |||
|
|||
public void testUpgrade() throws IOException { |
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.
++
BulkByScrollResponse response = client.migration().upgrade(request, RequestOptions.DEFAULT); | ||
// end::upgrade-execute | ||
|
||
}catch(ElasticsearchStatusException e){ |
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.
space }catch(
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.
++
@@ -0,0 +1,79 @@ | |||
[[java-rest-high-migration-upgrade]] |
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.
yea i think that we can wait till docs squares away what they are doing with our rest api docs before diving in to this.
|
||
import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester; | ||
|
||
public class IndexUpgradeSubmissionResponseTests 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.
this test will be refactor once we introduce a common task submission response class. Likely it would be just TaskId
@hub-cap updated the PR with review followup. Would you be able to have a look again? |
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.
Getting close. Great work with the thought behind the sync/async/submit stuff.
IndexUpgradeSubmissionResponse::fromXContent, Collections.emptySet()); | ||
} | ||
|
||
|
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.
spaces
} | ||
|
||
@Override | ||
public void writeTo(StreamOutput out) throws IOException { |
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.
Is this used anywhere?
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.
no, removing
indices = new String[]{index}; | ||
} | ||
|
||
public IndexUpgradeRequest(StreamInput in) throws IOException { |
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.
Is this used anywhere?
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.
nope, removing
* A request for performing Upgrade on Index | ||
* Part of Migration API | ||
*/ | ||
public class IndexUpgradeRequest extends MasterNodeReadRequest<IndexUpgradeRequest> implements IndicesRequest { |
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 should be just a TimedRequest
instead of a MasterNodeReadRequest
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.
agree, great suggestion
} | ||
|
||
@Override | ||
public ActionRequestValidationException validate() { |
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 can remove this once we make it a TimedRequest
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.
done
} | ||
|
||
@Override | ||
public void readFrom(StreamInput in) throws IOException { |
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.
is this used anywhere?
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.
no, removed
import org.elasticsearch.common.xcontent.ConstructingObjectParser; | ||
import org.elasticsearch.common.xcontent.ObjectParser; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
import org.elasticsearch.tasks.TaskId; |
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.
Do we need a TaskId? Can we just use a string here instead? Id love to not pull things in from server here if possible
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.
true, that is not ideal that it uses a class from server, but maybe we could copy or make our own TaskId class in HLRC?
I am a big fan of strong typed apis, and that abstracts nicely the concept of task identifier. I could refactor this class now, but since this is used in reindex and in getTask PRs I would prefer to refactor later
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.
IMHO if we always pass it to server as a single string and never need to modify it or make decisions based on some portion of the ID (as i understand it has > 1 bit of information in the string separated by a delimiter), then making it a string is fine by me.
That being said, if it is easier for a user to create a object with those 3 values rather than just passing in a string, Im all for using an object.
I dont know all the uses, but im a fan of keeping it simple. If a user is never going to do anything with those 3 different parts of the string, and they only store it and give it back to us as a single string, it does not make much sense in my mind to create a class representation for the 3 strings. Ofc it might make sense to have this on the server, since those 3 strings are useful as individual pieces :D
All that being said, im ok with duplicating a TaskId class in HLRC. Im not too picky :)
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.
What @hub-cap said. I too am unclear on the uses of TaskIDs and whether clients would need to break out component parts. I suppose even if they don't there's a potential upside to a typed object just because we could make them have private constructors so a client would only ever be able to give us IDs we'd previously given them, rather than any arbitrary string of their choosing.
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.
Im still leaning toward string. we have to have a way to deserialize bits from the wire into a TaskId, so there will be a way for a user to create their own TaskId, if they want to go that far.
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 am convinced too. Will refactor this to use TaskSubmissionResponse with taskId field of type String
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.
Agreed. In retrospect, typed TaskIDs might only be useful if the world ran on Java but Java apps will typically hand off control to a Javascript front-end where it would become untyped strings in subsequent comms.
private BooleanSupplier checkCompletionStatus(IndexUpgradeSubmissionResponse upgrade) { | ||
return () -> { | ||
try { | ||
Response response = client().performRequest(new Request("GET", "/_tasks/" + upgrade.getTask().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.
<3
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.
Looks like the docs can be DRY'd up (see #34925), and Id like to get the String VS TaskId issue solved, but then this will be good to merge.
|
||
private static Request prepareMigrateRequest(IndexUpgradeRequest indexUpgradeRequest, boolean waitForCompletion) { | ||
RequestConverters.EndpointBuilder endpointBuilder = new RequestConverters.EndpointBuilder() | ||
.addPathPartAsIs("_xpack/migration/upgrade") |
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.
you can comma separate these instead... i know the likelihood of us not using /
is low, but its best to not have them in this.
* A request for performing Upgrade on Index | ||
* Part of Migration API | ||
*/ | ||
|
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.
remove empty line
* Part of Migration API | ||
*/ | ||
|
||
public class IndexUpgradeRequest extends TimedRequest implements IndicesRequest { |
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.
do we need this IndicesRequest? We know that we should provide a getter for the IndicesOptions so im ok w/ removing this and the override as well.
import org.elasticsearch.common.xcontent.ConstructingObjectParser; | ||
import org.elasticsearch.common.xcontent.ObjectParser; | ||
import org.elasticsearch.common.xcontent.XContentParser; | ||
import org.elasticsearch.tasks.TaskId; |
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.
Im still leaning toward string. we have to have a way to deserialize bits from the wire into a TaskId, so there will be a way for a user to create their own TaskId, if they want to go that far.
@hub-cap updated PR and build is passing too! |
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.
One nit and one question, other than that lgtm. Im approving but I would still like ot see the answer to the question about array vs single string.
@@ -49,13 +50,14 @@ static Request submitMigrateTask(IndexUpgradeRequest indexUpgradeRequest) { | |||
|
|||
private static Request prepareMigrateRequest(IndexUpgradeRequest indexUpgradeRequest, boolean waitForCompletion) { | |||
RequestConverters.EndpointBuilder endpointBuilder = new RequestConverters.EndpointBuilder() | |||
.addPathPartAsIs("_xpack/migration/upgrade") | |||
.addCommaSeparatedPathParts(indexUpgradeRequest.indices()); | |||
.addPathPartAsIs("_xpack", "migration", "upgrade", indexUpgradeRequest.index()); |
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 has to be
.addPathPartAsIs("Strings", "hard", "coded")
.addPathPart(indexUpgradeRequest.index())
for sanitization
|
||
private String[] indices; | ||
private IndicesOptions indicesOptions = IndicesOptions.fromOptions(false, true, true, true); | ||
private String index; |
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 did we change this from an array of strings to a single one?
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.
for other kind of requests you can specify indices comma separated like _xpack/migration/assistance/index1,index2,index3
but for upgrade only one is allowed (as per documentation)
Implement high level client for migration upgrade API. It should wrap RestHighLevelClient and expose high level IndexUpgradeRequest (new), IndexTaskResponse for submissions with wait_for_completion=false and BulkByScrollResponse (already used) objects. refers: elastic#29827
Implement high level client for migration upgrade API. It should wrap RestHighLevelClient and expose high level IndexUpgradeRequest (new), IndexTaskResponse for submissions with wait_for_completion=false and BulkByScrollResponse (already used) objects. refers: #29827 Original backported PR (#34898) PR of the backport (#35528)
Implement high level client for migration upgrade API. It should wrap RestHighLevelClient and expose high level IndexUpgradeRequest (new) & BulkByScrollResponse (already used) objects.
endpoints:
sync & async:
POST /_xpack/migration/upgrade/<index_name>
sync with task api:
POST /_xpack/migration/upgrade/.watches?wait_for_completion=false
links:
Documentation reference:
https://www.elastic.co/guide/en/elasticsearch/reference/current/migration-api-assistance.html
X-pack API:
https://github.com/elastic/elasticsearch/blob/master/x-pack/plugin/src/test/resources/rest-api-spec/api/xpack.migration.get_assistance.json
refers: #29827