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

Add Cluster Put Settings API to the high level REST client #28633

Merged
merged 5 commits into from
Feb 15, 2018

Conversation

olcbean
Copy link
Contributor

@olcbean olcbean commented Feb 12, 2018

Add Cluster Put Settings API to the high level REST client
( equivalent to Cluster Update Setting in transport client )

Relates to #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?

1 similar comment
@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?

* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html"> Cluster Update Settings
* API on elastic.co</a>
*/
public ClusterUpdateSettingsResponse updateSettings(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest, Header... headers)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

hey @javanna I need some help with the naming?
In the rest-api-specs the api is cluster.put_settings, in the transport client and in the issue it is updateSettings. Should I rename to putSettings or leave it as updateSettings?

Copy link
Member

Choose a reason for hiding this comment

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

let's follow the SPEC and make it putSettings please ;)

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.

left some comments, looks good though, thanks @olcbean !

/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the cluster api.
* <p>
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster.html">Indices API on elastic.co</a>
Copy link
Member

Choose a reason for hiding this comment

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

s/Indices API/Cluster API

* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-update-settings.html"> Cluster Update Settings
* API on elastic.co</a>
*/
public ClusterUpdateSettingsResponse updateSettings(ClusterUpdateSettingsRequest clusterUpdateSettingsRequest, 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.

let's follow the SPEC and make it putSettings please ;)

Map<String, Object> setMap = getAsMap("/_cluster/settings");
String transietSetValue = (String) XContentMapValues.extractValue("transient." + transientSettingKey, setMap);
assertThat(transietSetValue, equalTo(transientSettingValue + ByteSizeUnit.BYTES.getSuffix()));
String persistentSetValue = (String) XContentMapValues.extractValue("persistent." + persistentSettingKey, setMap);
Copy link
Member

Choose a reason for hiding this comment

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

s/transiet/transient

assertThat(resetResponse.getPersistentSettings(), equalTo(Settings.EMPTY));

Map<String, Object> resetMap = getAsMap("/_cluster/settings");
String transietResetValue = (String) XContentMapValues.extractValue("transient." + transientSettingKey, resetMap);
Copy link
Member

Choose a reason for hiding this comment

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

s/transiet/transient

if (randomBoolean()) {
setRandomWaitForActiveShards(resizeRequest::setWaitForActiveShards, expectedParams);
}
setRandomWaitForActiveShards(resizeRequest::setWaitForActiveShards, expectedParams);
Copy link
Member

Choose a reason for hiding this comment

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

why these two changes? I meant to to randomly choose one of the two branches, but then still set the param only randomly.

Copy link
Contributor Author

@olcbean olcbean Feb 13, 2018

Choose a reason for hiding this comment

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

if (randomBoolean()) is already wrapped in the setRandom*. If we keep it here, then waitForRandomShards is set to a random value only 25% of the time.
I assumed that it was an oversight...

private static void setRandomWaitForActiveShards(Consumer<ActiveShardCount> setter, Map<String, String> expectedParams) {
        if (randomBoolean()) {
            String waitForActiveShardsString;
            int waitForActiveShards = randomIntBetween(-1, 5);
            if (waitForActiveShards == -1) {
                waitForActiveShardsString = "all";
            } else {
                waitForActiveShardsString = String.valueOf(waitForActiveShards);
            }
            setter.accept(ActiveShardCount.parseString(waitForActiveShardsString));
            expectedParams.put("wait_for_active_shards", waitForActiveShardsString);
        }
    }

Copy link
Member

Choose a reason for hiding this comment

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

oh right :) thanks


/**
* A response for a cluster update settings action.
*/
public class ClusterUpdateSettingsResponse extends AcknowledgedResponse {
public class ClusterUpdateSettingsResponse extends AcknowledgedResponse implements ToXContentObject {
Copy link
Member

Choose a reason for hiding this comment

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

shall we move RestClusterUpdateSettingsAction to use RestToXContentListener?

@@ -0,0 +1,128 @@
[[java-rest-high-cluster-update-settings]]
Copy link
Member

Choose a reason for hiding this comment

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

rename the file to put_settings?

provided as an argument
<2> Called in case of a failure. The raised exception is provided as an argument

[[java-rest-high-clustre-update-settings-response]]
Copy link
Member

Choose a reason for hiding this comment

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

s/clustre/cluster

--------------------------------------------------
<1> Indicates whether all of the nodes have acknowledged the request
<2> Indicates which transient settings have been applied
<3> Indicates which persistent settings have been applied
Copy link
Member

Choose a reason for hiding this comment

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

the docs don't quite build, could you fix that up?

--------------------------------------------------
include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[update-settings-settings-map]
--------------------------------------------------
<1> Settings provided as `Object` key-pairs, which gets converted to
Copy link
Member

Choose a reason for hiding this comment

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

you mean as a map?

@javanna javanna changed the title [WIP] Add Cluster Update Settings API to the high level REST client Add Cluster Update Settings API to the high level REST client Feb 13, 2018
import static java.util.Collections.emptySet;

/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for accessing the cluster api.
Copy link
Member

Choose a reason for hiding this comment

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

cluster api -> Cluster API

@@ -240,6 +241,15 @@ public final IndicesClient indices() {
return indicesClient;
}

/**
* Provides a {@link ClusterClient} which can be used to access the Clustre API.
Copy link
Member

Choose a reason for hiding this comment

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

Fix Clustre

String persistentSetValue = (String) XContentMapValues.extractValue("persistent." + persistentSettingKey, setMap);
assertThat(persistentSetValue, equalTo(persistentSettingValue));

ClusterUpdateSettingsRequest reserRequest = new ClusterUpdateSettingsRequest();
Copy link
Member

Choose a reason for hiding this comment

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

resetRequest


Settings transientSettings = Settings.builder().put(transientSettingKey, transientSettingValue, ByteSizeUnit.BYTES).build(); // <1>
Settings persistentSettings = Settings.builder().put(persistentSettingKey, persistentSettingValue).build();
// end::update-settings-create-settings
Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if splitting this into 2 parts, one for the transient settings and one for the persistent ones would be more readable?

// tag::update-settings-async
client.cluster().updateSettingsAsync(request, listener); // <1>
// end::update-settings-async
}
Copy link
Member

Choose a reason for hiding this comment

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

Missing latch.await()

include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[update-settings-request-cluster-settings]
--------------------------------------------------
<1> The transient settings provided as `Settigs`
<2> The persistent settings provided as `Settigs`
Copy link
Member

Choose a reason for hiding this comment

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

Fxi Settigs ;)

--------------------------------------------------

==== Cluster Settings
At least one setting be updated must be provided:
Copy link
Member

Choose a reason for hiding this comment

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

"to be updated"?

--------------------------------------------------
include-tagged::{doc-tests}/ClusterClientDocumentationIT.java[update-settings-request-flat-settings]
--------------------------------------------------
<1> Returned settings in flat format
Copy link
Member

Choose a reason for hiding this comment

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

Could it be more descriptive?

@olcbean
Copy link
Contributor Author

olcbean commented Feb 13, 2018

@javanna @tlrx thank you for the reviews! ( and sorry for the premature commit )

Now it should be ready for another round ;)

--------------------------------------------------
<1> Indicates whether all of the nodes have acknowledged the request
<2> Indicates which transient settings have been applied
<3> Indicates which persistent settings have been applied
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would like to shorten these ones by removing the leading Indicates. However it is used with Indicates in the indices section.

@olcbean olcbean changed the title Add Cluster Update Settings API to the high level REST client Add Cluster Put Settings API to the high level REST client Feb 14, 2018
@@ -138,6 +138,8 @@ public void onFailure(Exception e) {
// tag::indices-exists-async
client.indices().existsAsync(request, listener); // <1>
// end::indices-exists-async

assertTrue(latch.await(30L, TimeUnit.SECONDS));
Copy link
Member

Choose a reason for hiding this comment

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

ops :)

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 @olcbean I left some more comments.

public class ClusterUpdateSettingsRequest extends AcknowledgedRequest<ClusterUpdateSettingsRequest> implements ToXContentObject {

private static final String PERSISTENT = "persistent";
private static final String TRANSIENT = "transient";
Copy link
Member

Choose a reason for hiding this comment

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

nit: we could make these constants of type ParseField and then below in toXContent call field.getPreferredName()

@@ -150,6 +154,8 @@ public GetIndexRequest includeDefaults(boolean includeDefaults) {

/**
* Whether to return all default settings for each of the indices.
* Used only by the high-level REST client.
Copy link
Member

Choose a reason for hiding this comment

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

thanks for these changes

builder.endObject();
}
});
new RestToXContentListener<ClusterUpdateSettingsResponse>(channel));
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 remove the generic type? <> should be enough

final ClusterUpdateSettingsRequest request = createTestItem();
boolean humanReadable = randomBoolean();
final XContentType xContentType = XContentType.JSON;
BytesReference xContent = toShuffledXContentAndInsertRandomFields(request, xContentType, ToXContent.EMPTY_PARAMS, humanReadable);
Copy link
Member

Choose a reason for hiding this comment

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

inserting random fields is not a good idea for requests. we should parse them strictly. In fact if this test succeeds it means that we have a bug :) we should rather test that we are strict when parsing requests.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a test to make sure that inserting random fields fails here. Or is it too much?

BytesReference originalBytes = toShuffledXContent(toXContent, xContentType, params, humanReadable, exceptFieldNames);
BytesReference mutated;
if (randomBoolean()) {
mutated = insertRandomFields(xContentType, originalBytes, null, random());
Copy link
Member

Choose a reason for hiding this comment

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

given that in most cases we have two different test methods for this (with and without random fields), maybe we should not add this new method and rather do it like we did up until now? That said, I think I was not very diligent on this :)

persistentBuilder.keys().forEach(k -> {
assertThat(parsedPersistentBuilder.keys(), hasItem(equalTo(k)));
assertThat(parsedPersistentBuilder.get(k), equalTo(persistentBuilder.get(k)));
});
Copy link
Member

Choose a reason for hiding this comment

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

trying to figure out what happens when random fields are inserted among settings. I would expect the test to fail somehow, or maybe the arbitrary fields get parsed as setting and that is why you don't compare the two maps directly?

I wonder if randomizing at this level should be disabled, as its goal would be to verify that we are forward compatible when parsing, meaning that we will ignore a field/object if we don't know about it, as it could be a field added in a more recent version.

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 Settings will be simply parsed ( no strict validation ) and during execution will be compared tp the supported settings. I will disable the randomization for the settings, then the check is only for the 'top-level' fields.

private static final String TRANSIENT = "transient";

private static final ObjectParser<ClusterUpdateSettingsRequest, Void> PARSER = new ObjectParser<>("cluster_update_settings_request",
true, ClusterUpdateSettingsRequest::new);
Copy link
Member

Choose a reason for hiding this comment

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

ignoreUnknownFields should be set to false here, as it is a request

@@ -0,0 +1,129 @@
[[java-rest-high-cluster-put-settings]]
=== Cluster Put Settings API
Copy link
Member

Choose a reason for hiding this comment

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

I am sorry, can you change the title to Cluster Update Settings API, like we have in the es docs? Confusing, I know :)


String persistentSettingKey = EnableAllocationDecider.CLUSTER_ROUTING_ALLOCATION_ENABLE_SETTING.getKey();
String persistentSettingValue = EnableAllocationDecider.Allocation.NONE.name();
Settings persistentSettings = Settings.builder().put(persistentSettingKey, persistentSettingValue).build(); // <2>
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 wrapping these lines so they look better in the rendered docs?

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.

I left a few nits, this is ready though.

.put(persistentSettingKey, persistentSettingValue)
.build(); // <2>
// end::put-settings-create-settings
// @formatter:on
Copy link
Member

Choose a reason for hiding this comment

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

these are eclipse specific tags right? I don't think we'd want them in our code.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

According to the docs IntelliJ also supports them.
By default these tags are ignored ( at least for eclipse formatters ). I added them to make clear that these sections intentionally are not following the ES formatting rules.

Should I remove them?

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 I haven't seen them used before in our codebase. At some point we will automate formatting and these classes will have to somehow be ignored I think.

p -> p.startsWith("transient") || p.startsWith("persistent"), random());
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
() -> ClusterUpdateSettingsRequest.fromXContent(createParser(xContentType.xContent(), mutated)));
assertTrue(e.getMessage().matches("\\[cluster_update_settings_request\\] unknown field \\[\\w*\\], parser not found"));
Copy link
Member

Choose a reason for hiding this comment

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

maybe instead of randomizing, you could just have added a specific test method with a non randomized json that contains un unsupported field, to verify that an error is thrown. Just to simplify things a bit.

@@ -146,6 +146,7 @@
import static java.util.Collections.emptyMap;
import static java.util.Collections.singletonList;
import static org.elasticsearch.common.util.CollectionUtils.arrayAsArrayList;
import static org.elasticsearch.test.XContentTestUtils.insertRandomFields;
Copy link
Member

Choose a reason for hiding this comment

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

leftover?

[[java-rest-high-cluster-put-settings]]
=== Cluster Update Settings API

The Cluster Put Settings API allows to update cluster wide settings.
Copy link
Member

Choose a reason for hiding this comment

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

s/Put/Update ?

@javanna
Copy link
Member

javanna commented Feb 15, 2018

jenkins please test this

correct docs
remove tags disabling auto formatting
@javanna
Copy link
Member

javanna commented Feb 15, 2018

retest this please

@javanna javanna merged commit 02fc16f into elastic:master Feb 15, 2018
@javanna
Copy link
Member

javanna commented Feb 15, 2018

thanks again @olcbean !

@olcbean olcbean deleted the hlrc_cluster_update_settings branch February 16, 2018 12:14
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