Skip to content
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

Added Create Index support to high-level REST client #27351

Merged
merged 9 commits into from
Dec 7, 2017

Conversation

catalin-ursachi
Copy link
Contributor

@catalin-ursachi catalin-ursachi commented Nov 11, 2017

Adds one API covered by #27205

@elasticmachine
Copy link
Collaborator

Since this is a community submitted pull request, a Jenkins build has not been kicked off automatically. Can an Elastic organization member please verify the contents of this patch and then kick off a build manually?

@dnhatn
Copy link
Member

dnhatn commented Nov 11, 2017

@elasticmachine please test this.

execute(createIndexRequest, highLevelClient().indices()::createIndex, highLevelClient().indices()::createIndexAsync);
assertTrue(createIndexResponse.isAcknowledged());

assertTrue(indexExists(indexName));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The checks here could be expanded, to check for the alias, mapping and setting, once Get Index is implemented, I suppose; should I add a TODO?

Copy link
Member

Choose a reason for hiding this comment

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

would you mind using the low-level REST client to check this? You can parse the get index api response into a map and compare it to what you 'd expect?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good shout; alias filter creation was actually failing! Now fixed. ☺

Copy link
Member

Choose a reason for hiding this comment

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

nice!

builder.startObject(MAPPINGS.getPreferredName());

for (Map.Entry<String, String> entry : mappings.entrySet()) {
builder.rawField(entry.getKey(), new BytesArray(entry.getValue()), XContentType.JSON);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems infelicitous that we store the mappings as JSON-serialized Strings, and hence have to deserialize & reserialize them when making an HTTP request. It would presumably be nicer if we stored mappings as typed objects, akin to Aliases and Settings? Would that be a good idea/outside the scope of this PR?

Copy link
Member

Choose a reason for hiding this comment

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

yea this is annoying but I would not address it as part of this PR. Also, how would you type mappings? Maps of maps?

@javanna javanna self-assigned this Nov 13, 2017
Copy link
Member

@javanna javanna left a comment

Choose a reason for hiding this comment

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

thanks a lot @catalin-ursachi and sorry it took me a while to review it. It looks great, I left a few comments but nothing major. I will merge this in as soon as you addressed those.

Params parameters = Params.builder();
parameters.withTimeout(createIndexRequest.timeout());
parameters.withMasterTimeout(createIndexRequest.masterNodeTimeout());
parameters.withWaitForActiveShards(createIndexRequest.waitForActiveShards());
Copy link
Member

Choose a reason for hiding this comment

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

we also support a parameter called updateAllTypes here.

execute(createIndexRequest, highLevelClient().indices()::createIndex, highLevelClient().indices()::createIndexAsync);
assertTrue(createIndexResponse.isAcknowledged());

assertTrue(indexExists(indexName));
Copy link
Member

Choose a reason for hiding this comment

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

would you mind using the low-level REST client to check this? You can parse the get index api response into a map and compare it to what you 'd expect?


assertEquals(200, response.getStatusLine().getStatusCode());
assertTrue(response.isAcknowledged());
Copy link
Member

Choose a reason for hiding this comment

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

nit: I wonder if we should leave this method that uses the low-level REST client, given that we call it e.g. when testing delete index, otherwise we end up testing create index also as part of delete index.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Would obviously be trivial to revert to using the low-level client here, but I'd be wary of applying that principle later on - e.g., it we're testing Get Alias, it would be a lot more costly to create the test data using the low-level client, rather than the high-level client Create Alias; and so forth.

// end::delete-index-request-timeout
// tag::delete-index-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.timeout("1m"); // <2>
Copy link
Member

Choose a reason for hiding this comment

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

should this one be masterNodeTimeout too?

// end::create-index-request-timeout
// tag::create-index-request-masterTimeout
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
request.timeout("1m"); // <2>
Copy link
Member

Choose a reason for hiding this comment

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

should this also be masterNodeTimeout?

@@ -64,7 +64,7 @@ client.admin().indices().preparePutMapping("twitter") <1>
.setSource("{\n" + <3>
" \"properties\": {\n" +
" \"user_name\": {\n" +
" \"type\": \"string\"\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
"}")
Copy link
Member

Choose a reason for hiding this comment

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

good catches, but may I ask you to send a separate PR for these? I think the problem is that we are not testing these snippets, we should evaluate what to do about it in a different PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup; will create another PR.

/**
* Base testcase for indices admin unit testing
*/
public abstract class ESIndicesTestCase 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.

can you please add these methods to the CreateIndexRequestTests class where they are used? Let's' postpone the decision on where to put them once they need to be used from some other class too.

public static Alias randomAlias() {
Alias alias = new Alias(randomAlphaOfLength(5));

if (randomBoolean()) {
Copy link
Member

Choose a reason for hiding this comment

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

can you wrap the if in a new if(randomBoolean()) ? I want to make sure that we also test frequently the case where no routing is set.

builder.startObject(randomAlphaOfLength(5));

if (allowObjectField && randomBoolean()) {
randomMappingFields(builder, false);
Copy link
Member

Choose a reason for hiding this comment

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

do you think that we should limit the number of inner levels that we can have?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do you mean, we shouldn't limit it? I'll change the false to randomBoolean(), so we can go arbitrarily many levels in principle (but with decreasing likelihood).

}

int numberOfReplicas = randomIntBetween(0, 10);
if (numberOfReplicas >= 0) {
Copy link
Member

Choose a reason for hiding this comment

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

why the if? isn't it always true? Maybe you want to have an if(randomBoolean()) that controls whether we set the setting or not?

* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html">
* Create Index API on elastic.co</a>
*/
public CreateIndexResponse createIndex(CreateIndexRequest createIndexRequest, Header... headers) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

can you make it final please?

* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html">
* Create Index API on elastic.co</a>
*/
public void createIndexAsync(CreateIndexRequest createIndexRequest, ActionListener<CreateIndexResponse> listener, Header... headers) {
Copy link
Member

Choose a reason for hiding this comment

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

can you make it final please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Same for the delete index methods, I suppose?

Copy link
Member

Choose a reason for hiding this comment

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

yes please

@catalin-ursachi
Copy link
Contributor Author

Created #27629 for the 'put mappings' doc update.

Copy link
Member

@javanna javanna left a comment

Choose a reason for hiding this comment

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

thank you @catalin-ursachi I left some more comments, all minors, PR still looks good.

* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices.html">Indices API on elastic.co</a>
*/
public final class IndicesClient {
Copy link
Member

Choose a reason for hiding this comment

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

sorry I got confused with my own previous changes, let's leave this class final, then the final modifier is not necessary on each method. My bad.

execute(createIndexRequest, highLevelClient().indices()::createIndex, highLevelClient().indices()::createIndexAsync);
assertTrue(createIndexResponse.isAcknowledged());

assertTrue(indexExists(indexName));
Copy link
Member

Choose a reason for hiding this comment

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

nice!

execute(createIndexRequest, highLevelClient().indices()::createIndex, highLevelClient().indices()::createIndexAsync);
assertTrue(createIndexResponse.isAcknowledged());

Map<?, ?> indexMetaData = getIndexMetadata(indexName);
Copy link
Member

Choose a reason for hiding this comment

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

Can you use Map<String, Object> instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If I try to cast:

Map<String, Object> aliasData = (Map<String, Object>) aliasesData.get("alias_name");

IntelliJ highlights it with a warning that it constitutes an "Unchecked cast" (since type erasure makes casting to a specific type of Map meaningless anyway).
Should I ignore the warning and make the above change regardless?

Copy link
Member

Choose a reason for hiding this comment

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

you can add SuppressWarnings("unchecked") to the whole method like we do in other places.

setRandomWaitForActiveShards(createIndexRequest::waitForActiveShards, expectedParams);

boolean updateAllTypes = randomBoolean();
createIndexRequest.updateAllTypes(updateAllTypes);
Copy link
Member

Choose a reason for hiding this comment

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

can you set it only randomly so we also exercise the default value for it?


for (Alias expectedAlias : expected) {
for (Alias actualAlias : actual) {
if (expectedAlias.equals(actualAlias)) {
Copy link
Member

Choose a reason for hiding this comment

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

I guess we will never get here if they are not equal?

Copy link
Contributor Author

@catalin-ursachi catalin-ursachi Dec 4, 2017

Choose a reason for hiding this comment

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

Yeah; we check above that the two sets are equal; but Alias.equals returns true if the compared aliases have the same name. So, the sets will be equal iff they contain sets of aliases with the same names. At this stage, then, we check that aliases with the same name also have the same parameters.

Maybe we should also check routing params, here?

Copy link
Member

Choose a reason for hiding this comment

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

I see why you do that, it would be good to also check routing. It is odd that Alias#equals only looks at the name, not sure why but I wouldn't change that at the moment. I just meant that the if is redundant, isn't the equality check already part of the above assertion, which will make the test fail in case it's not satisfied?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, no; here, we're iterating over the two sets, but we only want to compare matching aliases. Without the if, we'd be comparing each alias from expected to every alias from actual - which would of course fail.

Copy link
Member

Choose a reason for hiding this comment

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

right! silly me ;) mind leaving a comment saying that we do this because Alias#equals only looks at name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done 🙂

@@ -113,6 +135,18 @@ private void assertMappingsEqual(Map<String, String> expected, Map<String, Strin
}
}

private void assertAliasesEqual(Set<Alias> expected, Set<Alias> actual) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

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

make it static?

builder.endObject();
}

public static Alias randomAlias() {
Copy link
Member

Choose a reason for hiding this comment

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

do these new methods need to be public? If not, let's keep them private and eventually make them public once we need them elsewhere?

@@ -137,4 +171,72 @@ private static CreateIndexRequest createTestItem() throws IOException {

return request;
}

public static Settings randomSettings() {
Copy link
Member

Choose a reason for hiding this comment

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

maybe rename to randomIndexSettings ?

builder.startObject(randomAlphaOfLength(5));

if (allowObjectField && randomBoolean()) {
randomMappingFields(builder, randomBoolean());
Copy link
Member

Choose a reason for hiding this comment

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

sorry, I see only now that you were already limiting the number of nested objects. My concern was to not end up with too many levels of nested objects. I think passing in false was good here, we do not need complicated mappings in this test.

Copy link
Member

@javanna javanna left a comment

Choose a reason for hiding this comment

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

thank you @catalin-ursachi I left some more comments, all minors, PR still looks good.

@javanna
Copy link
Member

javanna commented Dec 6, 2017

test this please

@javanna
Copy link
Member

javanna commented Dec 6, 2017

retest this please

@catalin-ursachi
Copy link
Contributor Author

None of the failures seemed related to the changes; will the merge with master have helped, or is the build just generally flaky?

@javanna
Copy link
Member

javanna commented Dec 6, 2017

don't worry @catalin-ursachi this is ready to be merged, failures are totally unrelated, we just were unlucky.

@javanna javanna merged commit f823cea into elastic:master Dec 7, 2017
@javanna javanna changed the title Added Create Index support to high-level REST client (#27205) Added Create Index support to high-level REST client Dec 7, 2017
@javanna
Copy link
Member

javanna commented Dec 7, 2017

thanks again @catalin-ursachi

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