add start trial API to HLRC (#33406)

Introduces client-specific request and response classes that do not
depend on the server

The `type` parameter is named `licenseType` in the response class to be
more descriptive. The parts that make up the acknowledged-required
response are given slightly different names than their server-response
types to be consistent with the naming in the put license API

Tests do not cover all cases because the integ test cluster starts up
with a trial license - this will be addressed in a future commit
This commit is contained in:
Andy Bristol 2018-10-17 08:02:04 -07:00 committed by GitHub
parent 139bbc3f03
commit 18aa1c1381
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 491 additions and 24 deletions

View File

@ -22,6 +22,8 @@ package org.elasticsearch.client;
import org.apache.http.HttpEntity;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.license.StartTrialRequest;
import org.elasticsearch.client.license.StartTrialResponse;
import org.elasticsearch.client.license.StartBasicRequest;
import org.elasticsearch.client.license.StartBasicResponse;
import org.elasticsearch.common.Strings;
@ -44,6 +46,7 @@ import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;
/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for
@ -123,6 +126,30 @@ public final class LicenseClient {
AcknowledgedResponse::fromXContent, listener, emptySet());
}
/**
* Starts a trial license on the cluster.
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public StartTrialResponse startTrial(StartTrialRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, LicenseRequestConverters::startTrial, options,
StartTrialResponse::fromXContent, singleton(403));
}
/**
* Asynchronously starts a trial license on the cluster.
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param listener the listener to be notified upon request completion
*/
public void startTrialAsync(StartTrialRequest request,
RequestOptions options,
ActionListener<StartTrialResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::startTrial, options,
StartTrialResponse::fromXContent, listener, singleton(403));
}
/**
* Initiates an indefinite basic license.
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized

View File

@ -23,6 +23,7 @@ import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.client.license.StartTrialRequest;
import org.elasticsearch.client.license.StartBasicRequest;
import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
@ -30,10 +31,7 @@ import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
public class LicenseRequestConverters {
static Request putLicense(PutLicenseRequest putLicenseRequest) {
String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("license")
.build();
String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_xpack", "license").build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
RequestConverters.Params parameters = new RequestConverters.Params(request);
parameters.withTimeout(putLicenseRequest.timeout());
@ -46,10 +44,7 @@ public class LicenseRequestConverters {
}
static Request getLicense(GetLicenseRequest getLicenseRequest) {
String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_xpack")
.addPathPartAsIs("license")
.build();
String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_xpack", "license").build();
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
RequestConverters.Params parameters = new RequestConverters.Params(request);
parameters.withLocal(getLicenseRequest.local());
@ -57,13 +52,26 @@ public class LicenseRequestConverters {
}
static Request deleteLicense(DeleteLicenseRequest deleteLicenseRequest) {
Request request = new Request(HttpDelete.METHOD_NAME, "/_xpack/license");
String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_xpack", "license").build();
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
RequestConverters.Params parameters = new RequestConverters.Params(request);
parameters.withTimeout(deleteLicenseRequest.timeout());
parameters.withMasterTimeout(deleteLicenseRequest.masterNodeTimeout());
return request;
}
static Request startTrial(StartTrialRequest startTrialRequest) {
final String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_xpack", "license", "start_trial").build();
final Request request = new Request(HttpPost.METHOD_NAME, endpoint);
RequestConverters.Params parameters = new RequestConverters.Params(request);
parameters.putParam("acknowledge", Boolean.toString(startTrialRequest.isAcknowledge()));
if (startTrialRequest.getLicenseType() != null) {
parameters.putParam("type", startTrialRequest.getLicenseType());
}
return request;
}
static Request startBasic(StartBasicRequest startBasicRequest) {
String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_xpack", "license", "start_basic")

View File

@ -980,7 +980,7 @@ final class RequestConverters {
return this;
}
EndpointBuilder addPathPartAsIs(String ... parts) {
EndpointBuilder addPathPartAsIs(String... parts) {
for (String part : parts) {
if (Strings.hasLength(part)) {
joiner.add(part);

View File

@ -0,0 +1,50 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.license;
import org.elasticsearch.client.Validatable;
import org.elasticsearch.common.Nullable;
public class StartTrialRequest implements Validatable {
private final boolean acknowledge;
private final String licenseType;
public StartTrialRequest() {
this(false);
}
public StartTrialRequest(boolean acknowledge) {
this(acknowledge, null);
}
public StartTrialRequest(boolean acknowledge, @Nullable String licenseType) {
this.acknowledge = acknowledge;
this.licenseType = licenseType;
}
public boolean isAcknowledge() {
return acknowledge;
}
public String getLicenseType() {
return licenseType;
}
}

View File

@ -0,0 +1,188 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.license;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.collect.Tuple;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParseException;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
public class StartTrialResponse {
private static final ConstructingObjectParser<StartTrialResponse, Void> PARSER = new ConstructingObjectParser<>(
"start_trial_response",
true,
(Object[] arguments, Void aVoid) -> {
final boolean acknowledged = (boolean) arguments[0];
final boolean trialWasStarted = (boolean) arguments[1];
final String licenseType = (String) arguments[2];
final String errorMessage = (String) arguments[3];
@SuppressWarnings("unchecked")
final Tuple<String, Map<String, String[]>> acknowledgeDetails = (Tuple<String, Map<String, String[]>>) arguments[4];
final String acknowledgeHeader;
final Map<String, String[]> acknowledgeMessages;
if (acknowledgeDetails != null) {
acknowledgeHeader = acknowledgeDetails.v1();
acknowledgeMessages = acknowledgeDetails.v2();
} else {
acknowledgeHeader = null;
acknowledgeMessages = null;
}
return new StartTrialResponse(acknowledged, trialWasStarted, licenseType, errorMessage, acknowledgeHeader,
acknowledgeMessages);
}
);
static {
PARSER.declareBoolean(constructorArg(), new ParseField("acknowledged"));
PARSER.declareBoolean(constructorArg(), new ParseField("trial_was_started"));
PARSER.declareString(optionalConstructorArg(), new ParseField("type"));
PARSER.declareString(optionalConstructorArg(), new ParseField("error_message"));
// todo consolidate this parsing with the parsing in PutLicenseResponse
PARSER.declareObject(optionalConstructorArg(), (parser, aVoid) -> {
final Map<String, String[]> acknowledgeMessages = new HashMap<>();
String message = null;
final Map<String, Object> parsedMap = parser.map();
for (Map.Entry<String, Object> entry : parsedMap.entrySet()) {
if (entry.getKey().equals("message")) {
if (entry.getValue() instanceof String) {
message = (String) entry.getValue();
} else {
throw new XContentParseException(parser.getTokenLocation(), "unexpected acknowledgement header type");
}
} else {
if (entry.getValue() instanceof List) {
final List<String> messageStrings = new ArrayList<>();
@SuppressWarnings("unchecked")
final List<Object> messageObjects = (List<Object>) entry.getValue();
for (Object messageObject : messageObjects) {
if (messageObject instanceof String) {
messageStrings.add((String) messageObject);
} else {
throw new XContentParseException(parser.getTokenLocation(), "expected text in acknowledgement message");
}
}
acknowledgeMessages.put(entry.getKey(), messageStrings.toArray(new String[messageStrings.size()]));
} else {
throw new XContentParseException(parser.getTokenLocation(), "unexpected acknowledgement message type");
}
}
}
if (message == null) {
throw new XContentParseException(parser.getTokenLocation(), "expected acknowledgement header");
}
return new Tuple<>(message, acknowledgeMessages);
}, new ParseField("acknowledge"));
}
public static StartTrialResponse fromXContent(XContentParser parser) throws IOException {
return PARSER.apply(parser, null);
}
private final boolean acknowledged;
private final boolean trialWasStarted;
private final String licenseType;
private final String errorMessage;
private final String acknowledgeHeader;
private final Map<String, String[]> acknowledgeMessages;
public StartTrialResponse(boolean acknowledged,
boolean trialWasStarted,
String licenseType,
String errorMessage,
String acknowledgeHeader,
Map<String, String[]> acknowledgeMessages) {
this.acknowledged = acknowledged;
this.trialWasStarted = trialWasStarted;
this.licenseType = licenseType;
this.errorMessage = errorMessage;
this.acknowledgeHeader = acknowledgeHeader;
this.acknowledgeMessages = acknowledgeMessages;
}
/**
* Returns true if the request that corresponds to this response acknowledged license changes that would occur as a result of starting
* a trial license
*/
public boolean isAcknowledged() {
return acknowledged;
}
/**
* Returns true if a trial license was started as a result of the request corresponding to this response. Returns false if the cluster
* did not start a trial, or a trial had already been started before the corresponding request was made
*/
public boolean isTrialWasStarted() {
return trialWasStarted;
}
/**
* If a trial license was started as a result of the request corresponding to this response (see {@link #isTrialWasStarted()}) then
* returns the type of license that was started on the cluster. Returns null otherwise
*/
public String getLicenseType() {
return licenseType;
}
/**
* If a trial license was not started as a result of the request corresponding to this response (see {@link #isTrialWasStarted()} then
* returns a brief message explaining why the trial could not be started. Returns false otherwise
*/
public String getErrorMessage() {
return errorMessage;
}
/**
* If the request corresponding to this response did not acknowledge licensing changes that would result from starting a trial license
* (see {@link #isAcknowledged()}), returns a message describing how the user must acknowledge licensing changes as a result of
* such a request. Returns null otherwise
*/
public String getAcknowledgeHeader() {
return acknowledgeHeader;
}
/**
* If the request corresponding to this response did not acknowledge licensing changes that would result from starting a trial license
* (see {@link #isAcknowledged()}, returns a map. The map's keys are names of commercial Elasticsearch features, and their values are
* messages about how those features will be affected by licensing changes as a result of starting a trial license
*/
public Map<String, String[]> getAcknowledgeMessages() {
return acknowledgeMessages;
}
}

View File

@ -16,11 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client;
import org.elasticsearch.Build;
import org.elasticsearch.client.license.StartBasicRequest;
import org.elasticsearch.client.license.StartBasicResponse;
import org.elasticsearch.client.license.StartTrialRequest;
import org.elasticsearch.client.license.StartTrialResponse;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
@ -31,7 +34,6 @@ import org.junit.BeforeClass;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
@ -42,7 +44,13 @@ import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.empty;
public class LicensingIT extends ESRestHighLevelClientTestCase {
public class LicenseIT extends ESRestHighLevelClientTestCase {
/*
* todo there are some cases we can't test here because this gradle project starts the integ test cluster so that it'll generate
* a trial license at startup. we need to add a separate gradle project for the license-related tests so that we can start the
* integ test cluster without generating a trial license
*/
@BeforeClass
public static void checkForSnapshot() {
@ -55,6 +63,37 @@ public class LicensingIT extends ESRestHighLevelClientTestCase {
putTrialLicense();
}
public void testStartTrial() throws Exception {
// todo add case where we successfully start a trial - see note above
// case where we don't acknowledge trial license conditions
{
final StartTrialRequest request = new StartTrialRequest();
final StartTrialResponse response = highLevelClient().license().startTrial(request, RequestOptions.DEFAULT);
assertThat(response.isAcknowledged(), equalTo(false));
assertThat(response.isTrialWasStarted(), equalTo(false));
assertThat(response.getLicenseType(), nullValue());
assertThat(response.getErrorMessage(), equalTo("Operation failed: Needs acknowledgement."));
assertThat(response.getAcknowledgeHeader(), containsString("This API initiates a free 30-day trial for all platinum features"));
assertNotEmptyAcknowledgeMessages(response.getAcknowledgeMessages());
}
// case where we acknowledge, but the trial is already started at cluster startup
{
final StartTrialRequest request = new StartTrialRequest(true);
final StartTrialResponse response = highLevelClient().license().startTrial(request, RequestOptions.DEFAULT);
assertThat(response.isAcknowledged(), equalTo(true));
assertThat(response.isTrialWasStarted(), equalTo(false));
assertThat(response.getLicenseType(), nullValue());
assertThat(response.getErrorMessage(), equalTo("Operation failed: Trial was already activated."));
assertThat(response.getAcknowledgeHeader(), nullValue());
assertThat(response.getAcknowledgeMessages(), nullValue());
}
}
public static void putTrialLicense() throws IOException {
assumeTrue("Trial license is only valid when tested against snapshot/test builds",
Build.CURRENT.isSnapshot());
@ -76,9 +115,9 @@ public class LicensingIT extends ESRestHighLevelClientTestCase {
.put("start_date_in_millis", "-1")
.put("signature",
"AAAABAAAAA3FXON9kGmNqmH+ASDWAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAAcdKHL0BfM2uqTgT7BDuFxX5lb"
+ "t/bHDVJ421Wwgm5p3IMbw/W13iiAHz0hhDziF7acJbc/y65L+BKGtVC1gSSHeLDHaAD66VrjKxfc7VbGyJIAYBOdujf0rheurmaD3IcNo"
+ "/tWDjCdtTwrNziFkorsGcPadBP5Yc6csk3/Q74DlfiYweMBxLUfkBERwxwd5OQS6ujGvl/4bb8p5zXvOw8vMSaAXSXXnExP6lam+0934W"
+ "0kHvU7IGk+fCUjOaiSWKSoE4TEcAtVNYj/oRoRtfQ1KQGpdCHxTHs1BimdZaG0nBHDsvhYlVVLSvHN6QzqsHWgFDG6JJxhtU872oTRSUHA=")
+ "t/bHDVJ421Wwgm5p3IMbw/W13iiAHz0hhDziF7acJbc/y65L+BKGtVC1gSSHeLDHaAD66VrjKxfc7VbGyJIAYBOdujf0rheurmaD3IcNo"
+ "/tWDjCdtTwrNziFkorsGcPadBP5Yc6csk3/Q74DlfiYweMBxLUfkBERwxwd5OQS6ujGvl/4bb8p5zXvOw8vMSaAXSXXnExP6lam+0934W"
+ "0kHvU7IGk+fCUjOaiSWKSoE4TEcAtVNYj/oRoRtfQ1KQGpdCHxTHs1BimdZaG0nBHDsvhYlVVLSvHN6QzqsHWgFDG6JJxhtU872oTRSUHA=")
.immutableMap()))
.endObject());
@ -103,7 +142,7 @@ public class LicensingIT extends ESRestHighLevelClientTestCase {
assertThat(response.getAcknowledgeMessage(),
containsString("This license update requires acknowledgement. " +
"To acknowledge the license, please read the following messages and call /start_basic again"));
assertNotEmptyAcknowledgeMessages(response);
assertNotEmptyAcknowledgeMessages(response.getAcknowledgeMessages());
}
// case where we acknowledge and the basic is started successfully
{
@ -117,12 +156,11 @@ public class LicensingIT extends ESRestHighLevelClientTestCase {
}
}
private static void assertNotEmptyAcknowledgeMessages(StartBasicResponse response) {
assertThat(response.getAcknowledgeMessages().entrySet(), not(empty()));
for (Map.Entry<String, String[]> entry : response.getAcknowledgeMessages().entrySet()) {
private static void assertNotEmptyAcknowledgeMessages(Map<String, String[]> acknowledgeMessages) {
assertThat(acknowledgeMessages.entrySet(), not(empty()));
for (Map.Entry<String, String[]> entry : acknowledgeMessages.entrySet()) {
assertThat(entry.getKey(), not(isEmptyOrNullString()));
final List<String> messages = Arrays.asList(entry.getValue());
for (String message : messages) {
for (String message : entry.getValue()) {
assertThat(message, not(isEmptyOrNullString()));
}
}

View File

@ -16,9 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client;
import org.apache.http.client.methods.HttpPost;
import org.elasticsearch.client.license.StartTrialRequest;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.client.license.StartBasicRequest;
import org.elasticsearch.test.ESTestCase;
@ -26,13 +28,36 @@ import org.elasticsearch.test.ESTestCase;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.nullValue;
import static org.elasticsearch.client.RequestConvertersTests.setRandomMasterTimeout;
import static org.elasticsearch.client.RequestConvertersTests.setRandomTimeout;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.nullValue;
public class LicenseRequestConvertersTests extends ESTestCase {
public void testStartTrial() {
final boolean acknowledge = randomBoolean();
final String licenseType = randomBoolean()
? randomAlphaOfLengthBetween(3, 10)
: null;
final Map<String, String> expectedParams = new HashMap<>();
expectedParams.put("acknowledge", Boolean.toString(acknowledge));
if (licenseType != null) {
expectedParams.put("type", licenseType);
}
final StartTrialRequest hlrcRequest = new StartTrialRequest(acknowledge, licenseType);
final Request restRequest = LicenseRequestConverters.startTrial(hlrcRequest);
assertThat(restRequest.getMethod(), equalTo(HttpPost.METHOD_NAME));
assertThat(restRequest.getEndpoint(), equalTo("/_xpack/license/start_trial"));
assertThat(restRequest.getParameters(), equalTo(expectedParams));
assertThat(restRequest.getEntity(), nullValue());
}
public void testStartBasic() {
final boolean acknowledge = randomBoolean();
StartBasicRequest startBasicRequest = new StartBasicRequest(acknowledge);

View File

@ -26,6 +26,8 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.license.StartTrialRequest;
import org.elasticsearch.client.license.StartTrialResponse;
import org.elasticsearch.client.license.StartBasicRequest;
import org.elasticsearch.client.license.StartBasicResponse;
import org.elasticsearch.common.Booleans;
@ -43,12 +45,14 @@ import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import static org.elasticsearch.client.LicensingIT.putTrialLicense;
import static org.elasticsearch.client.LicenseIT.putTrialLicense;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.startsWith;
import static org.hamcrest.core.Is.is;
/**
* Documentation for Licensing APIs in the high level java client.
@ -232,6 +236,61 @@ public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {
}
}
public void testStartTrial() throws Exception {
RestHighLevelClient client = highLevelClient();
{
// tag::start-trial-execute
StartTrialRequest request = new StartTrialRequest(true); // <1>
StartTrialResponse response = client.license().startTrial(request, RequestOptions.DEFAULT);
// end::start-trial-execute
// tag::start-trial-response
boolean acknowledged = response.isAcknowledged(); // <1>
boolean trialWasStarted = response.isTrialWasStarted(); // <2>
String licenseType = response.getLicenseType(); // <3>
String errorMessage = response.getErrorMessage(); // <4>
String acknowledgeHeader = response.getAcknowledgeHeader(); // <5>
Map<String, String[]> acknowledgeMessages = response.getAcknowledgeMessages(); // <6>
// end::start-trial-response
assertTrue(acknowledged);
assertFalse(trialWasStarted);
assertThat(licenseType, nullValue());
assertThat(errorMessage, is("Operation failed: Trial was already activated."));
assertThat(acknowledgeHeader, nullValue());
assertThat(acknowledgeMessages, nullValue());
}
{
StartTrialRequest request = new StartTrialRequest();
// tag::start-trial-execute-listener
ActionListener<StartTrialResponse> listener = new ActionListener<StartTrialResponse>() {
@Override
public void onResponse(StartTrialResponse response) {
// <1>
}
@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::start-trial-execute-listener
final CountDownLatch latch = new CountDownLatch(1);
listener = new LatchedActionListener<>(listener, latch);
// tag::start-trial-execute-async
client.license().startTrialAsync(request, RequestOptions.DEFAULT, listener);
// end::start-trial-execute-async
assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
public void testPostStartBasic() throws Exception {
RestHighLevelClient client = highLevelClient();
{

View File

@ -0,0 +1,70 @@
[[java-rest-high-start-trial]]
=== Start Trial
[[java-rest-high-start-trial-execution]]
==== Execution
This API creates and enables a trial license using the `startTrial()`
method.
["source","java",subs="attributes,callouts,macros"]
---------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-trial-execute]
---------------------------------------------------
<1> Sets the "acknowledge" parameter to true, indicating the user has
acknowledged that starting a trial license may affect commercial features
[[java-rest-high-start-trial-response]]
==== Response
The returned `StartTrialResponse` returns a field indicating whether the
trial was started. If it was started, the response returns a the type of
license started. If it was not started, it returns an error message describing
why.
Acknowledgement messages may also be returned if this API was called without
the `acknowledge` flag set to `true`. In this case you need to display the
messages to the end user and if they agree, resubmit the request with the
`acknowledge` flag set to `true`. Please note that the response will still
return a 200 return code even if it requires an acknowledgement. So, it is
necessary to check the `acknowledged` flag.
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-trial-response]
--------------------------------------------------
<1> Whether or not the request had the `acknowledge` flag set
<2> Whether or not this request caused a trial to start
<3> If this request caused a trial to start, which type of license it
registered
<4> If this request did not cause a trial to start, a message explaining why
<5> If the user's request did not have the `acknowledge` flag set, a summary
of the user's acknowledgement required for this API
<6> If the user's request did not have the `acknowledge` flag set, contains
keys of commercial features and values of messages describing how they will
be affected by licensing changes as the result of starting a trial
[[java-rest-high-start-trial-async]]
==== Asynchronous execution
This request can be executed asynchronously:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-trial-execute-async]
--------------------------------------------------
The asynchronous method does not block and returns immediately. Once it is
completed the `ActionListener` is called back using the `onResponse` method
if the execution successfully completed or using the `onFailure` method if
it failed.
A typical listener for `StartTrialResponse` looks like:
["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-trial-execute-listener]
--------------------------------------------------
<1> Called when the execution is successfully completed. The response is
provided as an argument
<2> Called in case of failure. The raised exception is provided as an argument

View File

@ -214,11 +214,13 @@ The Java High Level REST Client supports the following Licensing APIs:
* <<java-rest-high-put-license>>
* <<java-rest-high-get-license>>
* <<java-rest-high-delete-license>>
* <<java-rest-high-start-trial>>
* <<java-rest-high-start-basic>>
include::licensing/put-license.asciidoc[]
include::licensing/get-license.asciidoc[]
include::licensing/delete-license.asciidoc[]
include::licensing/start-trial.asciidoc[]
include::licensing/start-basic.asciidoc[]
== Machine Learning APIs