HLRC: Add support for XPack Post Start Basic Licence API (#33606)
Relates to #29827
This commit is contained in:
parent
936faba6c4
commit
230ad5339b
|
@ -22,6 +22,8 @@ package org.elasticsearch.client;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
|
import org.elasticsearch.client.license.StartBasicRequest;
|
||||||
|
import org.elasticsearch.client.license.StartBasicResponse;
|
||||||
import org.elasticsearch.common.Strings;
|
import org.elasticsearch.common.Strings;
|
||||||
import org.elasticsearch.common.io.Streams;
|
import org.elasticsearch.common.io.Streams;
|
||||||
import org.elasticsearch.common.xcontent.DeprecationHandler;
|
import org.elasticsearch.common.xcontent.DeprecationHandler;
|
||||||
|
@ -121,6 +123,28 @@ public final class LicenseClient {
|
||||||
AcknowledgedResponse::fromXContent, listener, emptySet());
|
AcknowledgedResponse::fromXContent, listener, emptySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initiates an indefinite basic license.
|
||||||
|
* @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 StartBasicResponse startBasic(StartBasicRequest request, RequestOptions options) throws IOException {
|
||||||
|
return restHighLevelClient.performRequestAndParseEntity(request, LicenseRequestConverters::startBasic, options,
|
||||||
|
StartBasicResponse::fromXContent, emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronously initiates an indefinite basic license.
|
||||||
|
* @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 startBasicAsync(StartBasicRequest request, RequestOptions options,
|
||||||
|
ActionListener<StartBasicResponse> listener) {
|
||||||
|
restHighLevelClient.performRequestAsyncAndParseEntity(request, LicenseRequestConverters::startBasic, options,
|
||||||
|
StartBasicResponse::fromXContent, listener, emptySet());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts an entire response into a json string
|
* Converts an entire response into a json string
|
||||||
*
|
*
|
||||||
|
|
|
@ -21,7 +21,9 @@ package org.elasticsearch.client;
|
||||||
|
|
||||||
import org.apache.http.client.methods.HttpDelete;
|
import org.apache.http.client.methods.HttpDelete;
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.client.methods.HttpPut;
|
import org.apache.http.client.methods.HttpPut;
|
||||||
|
import org.elasticsearch.client.license.StartBasicRequest;
|
||||||
import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
|
import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
|
||||||
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
|
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
|
||||||
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
|
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
|
||||||
|
@ -61,4 +63,18 @@ public class LicenseRequestConverters {
|
||||||
parameters.withMasterTimeout(deleteLicenseRequest.masterNodeTimeout());
|
parameters.withMasterTimeout(deleteLicenseRequest.masterNodeTimeout());
|
||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Request startBasic(StartBasicRequest startBasicRequest) {
|
||||||
|
String endpoint = new RequestConverters.EndpointBuilder()
|
||||||
|
.addPathPartAsIs("_xpack", "license", "start_basic")
|
||||||
|
.build();
|
||||||
|
Request request = new Request(HttpPost.METHOD_NAME, endpoint);
|
||||||
|
RequestConverters.Params parameters = new RequestConverters.Params(request);
|
||||||
|
parameters.withTimeout(startBasicRequest.timeout());
|
||||||
|
parameters.withMasterTimeout(startBasicRequest.masterNodeTimeout());
|
||||||
|
if (startBasicRequest.isAcknowledge()) {
|
||||||
|
parameters.putParam("acknowledge", "true");
|
||||||
|
}
|
||||||
|
return request;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -980,9 +980,11 @@ final class RequestConverters {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
EndpointBuilder addPathPartAsIs(String part) {
|
EndpointBuilder addPathPartAsIs(String ... parts) {
|
||||||
if (Strings.hasLength(part)) {
|
for (String part : parts) {
|
||||||
joiner.add(part);
|
if (Strings.hasLength(part)) {
|
||||||
|
joiner.add(part);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ package org.elasticsearch.client;
|
||||||
|
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
|
||||||
|
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base request for any requests that supply timeouts.
|
* A base request for any requests that supply timeouts.
|
||||||
*
|
*
|
||||||
|
@ -28,8 +30,11 @@ import org.elasticsearch.common.unit.TimeValue;
|
||||||
*/
|
*/
|
||||||
public class TimedRequest implements Validatable {
|
public class TimedRequest implements Validatable {
|
||||||
|
|
||||||
private TimeValue timeout;
|
public static final TimeValue DEFAULT_ACK_TIMEOUT = timeValueSeconds(30);
|
||||||
private TimeValue masterTimeout;
|
public static final TimeValue DEFAULT_MASTER_NODE_TIMEOUT = TimeValue.timeValueSeconds(30);
|
||||||
|
|
||||||
|
private TimeValue timeout = DEFAULT_ACK_TIMEOUT;
|
||||||
|
private TimeValue masterTimeout = DEFAULT_MASTER_NODE_TIMEOUT;
|
||||||
|
|
||||||
public void setTimeout(TimeValue timeout) {
|
public void setTimeout(TimeValue timeout) {
|
||||||
this.timeout = timeout;
|
this.timeout = timeout;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* 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.TimedRequest;
|
||||||
|
|
||||||
|
public class StartBasicRequest extends TimedRequest {
|
||||||
|
private final boolean acknowledge;
|
||||||
|
|
||||||
|
public StartBasicRequest() {
|
||||||
|
this(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StartBasicRequest(boolean acknowledge) {
|
||||||
|
this.acknowledge = acknowledge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAcknowledge() {
|
||||||
|
return acknowledge;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* 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 org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||||
|
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.optionalConstructorArg;
|
||||||
|
import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken;
|
||||||
|
|
||||||
|
public class StartBasicResponse {
|
||||||
|
|
||||||
|
private static final ConstructingObjectParser<StartBasicResponse, Void> PARSER = new ConstructingObjectParser<>(
|
||||||
|
"start_basic_response", true, (a, v) -> {
|
||||||
|
boolean basicWasStarted = (Boolean) a[0];
|
||||||
|
String errorMessage = (String) a[1];
|
||||||
|
|
||||||
|
if (basicWasStarted) {
|
||||||
|
return new StartBasicResponse(StartBasicResponse.Status.GENERATED_BASIC);
|
||||||
|
}
|
||||||
|
StartBasicResponse.Status status = StartBasicResponse.Status.fromErrorMessage(errorMessage);
|
||||||
|
@SuppressWarnings("unchecked") Tuple<String, Map<String, String[]>> acknowledgements = (Tuple<String, Map<String, String[]>>) a[2];
|
||||||
|
return new StartBasicResponse(status, acknowledgements.v2(), acknowledgements.v1());
|
||||||
|
});
|
||||||
|
|
||||||
|
static {
|
||||||
|
PARSER.declareBoolean(constructorArg(), new ParseField("basic_was_started"));
|
||||||
|
PARSER.declareString(optionalConstructorArg(), new ParseField("error_message"));
|
||||||
|
PARSER.declareObject(optionalConstructorArg(), (parser, v) -> {
|
||||||
|
Map<String, String[]> acknowledgeMessages = new HashMap<>();
|
||||||
|
String message = null;
|
||||||
|
XContentParser.Token token;
|
||||||
|
String currentFieldName = null;
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
|
currentFieldName = parser.currentName();
|
||||||
|
} else {
|
||||||
|
if (currentFieldName == null) {
|
||||||
|
throw new XContentParseException(parser.getTokenLocation(), "expected message header or acknowledgement");
|
||||||
|
}
|
||||||
|
if (new ParseField("message").getPreferredName().equals(currentFieldName)) {
|
||||||
|
ensureExpectedToken(XContentParser.Token.VALUE_STRING, token, parser::getTokenLocation);
|
||||||
|
message = parser.text();
|
||||||
|
} else {
|
||||||
|
if (token != XContentParser.Token.START_ARRAY) {
|
||||||
|
throw new XContentParseException(parser.getTokenLocation(), "unexpected acknowledgement type");
|
||||||
|
}
|
||||||
|
List<String> acknowledgeMessagesList = new ArrayList<>();
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
ensureExpectedToken(XContentParser.Token.VALUE_STRING, token, parser::getTokenLocation);
|
||||||
|
acknowledgeMessagesList.add(parser.text());
|
||||||
|
}
|
||||||
|
acknowledgeMessages.put(currentFieldName, acknowledgeMessagesList.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new Tuple<>(message, acknowledgeMessages);
|
||||||
|
},
|
||||||
|
new ParseField("acknowledge"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String[]> acknowledgeMessages;
|
||||||
|
private String acknowledgeMessage;
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
GENERATED_BASIC(true, null, RestStatus.OK),
|
||||||
|
ALREADY_USING_BASIC(false, "Operation failed: Current license is basic.", RestStatus.FORBIDDEN),
|
||||||
|
NEED_ACKNOWLEDGEMENT(false, "Operation failed: Needs acknowledgement.", RestStatus.OK);
|
||||||
|
|
||||||
|
private final boolean isBasicStarted;
|
||||||
|
private final String errorMessage;
|
||||||
|
private final RestStatus restStatus;
|
||||||
|
|
||||||
|
Status(boolean isBasicStarted, String errorMessage, RestStatus restStatus) {
|
||||||
|
this.isBasicStarted = isBasicStarted;
|
||||||
|
this.errorMessage = errorMessage;
|
||||||
|
this.restStatus = restStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
String getErrorMessage() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isBasicStarted() {
|
||||||
|
return isBasicStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
static StartBasicResponse.Status fromErrorMessage(final String errorMessage) {
|
||||||
|
final StartBasicResponse.Status[] values = StartBasicResponse.Status.values();
|
||||||
|
for (StartBasicResponse.Status status : values) {
|
||||||
|
if (Objects.equals(status.errorMessage, errorMessage)) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("No status for error message ['" + errorMessage + "']");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private StartBasicResponse.Status status;
|
||||||
|
|
||||||
|
public StartBasicResponse() {
|
||||||
|
}
|
||||||
|
|
||||||
|
StartBasicResponse(StartBasicResponse.Status status) {
|
||||||
|
this(status, Collections.emptyMap(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
StartBasicResponse(StartBasicResponse.Status status,
|
||||||
|
Map<String, String[]> acknowledgeMessages, String acknowledgeMessage) {
|
||||||
|
this.status = status;
|
||||||
|
this.acknowledgeMessages = acknowledgeMessages;
|
||||||
|
this.acknowledgeMessage = acknowledgeMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAcknowledged() {
|
||||||
|
return status != StartBasicResponse.Status.NEED_ACKNOWLEDGEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBasicStarted() {
|
||||||
|
return status.isBasicStarted;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return status.errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAcknowledgeMessage() {
|
||||||
|
return acknowledgeMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String[]> getAcknowledgeMessages() {
|
||||||
|
return acknowledgeMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StartBasicResponse fromXContent(XContentParser parser) throws IOException {
|
||||||
|
return PARSER.parse(parser, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
||||||
|
import org.elasticsearch.client.license.StartBasicRequest;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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 testStartBasic() {
|
||||||
|
final boolean acknowledge = randomBoolean();
|
||||||
|
StartBasicRequest startBasicRequest = new StartBasicRequest(acknowledge);
|
||||||
|
Map<String, String> expectedParams = new HashMap<>();
|
||||||
|
if (acknowledge) {
|
||||||
|
expectedParams.put("acknowledge", Boolean.TRUE.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
setRandomTimeout(startBasicRequest, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
|
||||||
|
setRandomMasterTimeout(startBasicRequest, expectedParams);
|
||||||
|
Request request = LicenseRequestConverters.startBasic(startBasicRequest);
|
||||||
|
|
||||||
|
assertThat(request.getMethod(), equalTo(HttpPost.METHOD_NAME));
|
||||||
|
assertThat(request.getEndpoint(), equalTo("/_xpack/license/start_basic"));
|
||||||
|
assertThat(request.getParameters(), equalTo(expectedParams));
|
||||||
|
assertThat(request.getEntity(), is(nullValue()));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
import org.elasticsearch.Build;
|
||||||
|
import org.elasticsearch.client.license.StartBasicRequest;
|
||||||
|
import org.elasticsearch.client.license.StartBasicResponse;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.collect.MapBuilder;
|
||||||
|
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
|
||||||
|
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
|
||||||
|
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
|
||||||
|
import org.junit.After;
|
||||||
|
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;
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
import static org.hamcrest.CoreMatchers.nullValue;
|
||||||
|
import static org.hamcrest.Matchers.isEmptyOrNullString;
|
||||||
|
import static org.hamcrest.Matchers.not;
|
||||||
|
import static org.hamcrest.Matchers.empty;
|
||||||
|
|
||||||
|
public class LicensingIT extends ESRestHighLevelClientTestCase {
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void checkForSnapshot() {
|
||||||
|
assumeTrue("Trial license used to rollback is only valid when tested against snapshot/test builds",
|
||||||
|
Build.CURRENT.isSnapshot());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void rollbackToTrial() throws IOException {
|
||||||
|
putTrialLicense();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void putTrialLicense() throws IOException {
|
||||||
|
assumeTrue("Trial license is only valid when tested against snapshot/test builds",
|
||||||
|
Build.CURRENT.isSnapshot());
|
||||||
|
|
||||||
|
// use a hard-coded trial license for 20 yrs to be able to roll back from another licenses
|
||||||
|
final String licenseDefinition = Strings.toString(jsonBuilder()
|
||||||
|
.startObject()
|
||||||
|
.field("licenses", Arrays.asList(
|
||||||
|
MapBuilder.<String, Object>newMapBuilder()
|
||||||
|
.put("uid", "96fc37c6-6fc9-43e2-a40d-73143850cd72")
|
||||||
|
.put("type", "trial")
|
||||||
|
// 2018-10-16 07:02:48 UTC
|
||||||
|
.put("issue_date_in_millis", "1539673368158")
|
||||||
|
// 2038-10-11 07:02:48 UTC, 20 yrs later
|
||||||
|
.put("expiry_date_in_millis", "2170393368158")
|
||||||
|
.put("max_nodes", "5")
|
||||||
|
.put("issued_to", "client_rest-high-level_integTestCluster")
|
||||||
|
.put("issuer", "elasticsearch")
|
||||||
|
.put("start_date_in_millis", "-1")
|
||||||
|
.put("signature",
|
||||||
|
"AAAABAAAAA3FXON9kGmNqmH+ASDWAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAAcdKHL0BfM2uqTgT7BDuFxX5lb"
|
||||||
|
+ "t/bHDVJ421Wwgm5p3IMbw/W13iiAHz0hhDziF7acJbc/y65L+BKGtVC1gSSHeLDHaAD66VrjKxfc7VbGyJIAYBOdujf0rheurmaD3IcNo"
|
||||||
|
+ "/tWDjCdtTwrNziFkorsGcPadBP5Yc6csk3/Q74DlfiYweMBxLUfkBERwxwd5OQS6ujGvl/4bb8p5zXvOw8vMSaAXSXXnExP6lam+0934W"
|
||||||
|
+ "0kHvU7IGk+fCUjOaiSWKSoE4TEcAtVNYj/oRoRtfQ1KQGpdCHxTHs1BimdZaG0nBHDsvhYlVVLSvHN6QzqsHWgFDG6JJxhtU872oTRSUHA=")
|
||||||
|
.immutableMap()))
|
||||||
|
.endObject());
|
||||||
|
|
||||||
|
final PutLicenseRequest request = new PutLicenseRequest();
|
||||||
|
request.setAcknowledge(true);
|
||||||
|
request.setLicenseDefinition(licenseDefinition);
|
||||||
|
final PutLicenseResponse response = highLevelClient().license().putLicense(request, RequestOptions.DEFAULT);
|
||||||
|
assertThat(response.isAcknowledged(), equalTo(true));
|
||||||
|
assertThat(response.status(), equalTo(LicensesStatus.VALID));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStartBasic() throws Exception {
|
||||||
|
// we don't test the case where we successfully start a basic because the integ test cluster generates one on startup
|
||||||
|
// and we don't have a good way to prevent that / work around it in this test project
|
||||||
|
// case where we don't acknowledge basic license conditions
|
||||||
|
{
|
||||||
|
final StartBasicRequest request = new StartBasicRequest();
|
||||||
|
final StartBasicResponse response = highLevelClient().license().startBasic(request, RequestOptions.DEFAULT);
|
||||||
|
assertThat(response.isAcknowledged(), equalTo(false));
|
||||||
|
assertThat(response.isBasicStarted(), equalTo(false));
|
||||||
|
assertThat(response.getErrorMessage(), equalTo("Operation failed: Needs acknowledgement."));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
// case where we acknowledge and the basic is started successfully
|
||||||
|
{
|
||||||
|
final StartBasicRequest request = new StartBasicRequest(true);
|
||||||
|
final StartBasicResponse response = highLevelClient().license().startBasic(request, RequestOptions.DEFAULT);
|
||||||
|
assertThat(response.isAcknowledged(), equalTo(true));
|
||||||
|
assertThat(response.isBasicStarted(), equalTo(true));
|
||||||
|
assertThat(response.getErrorMessage(), nullValue());
|
||||||
|
assertThat(response.getAcknowledgeMessage(), nullValue());
|
||||||
|
assertThat(response.getAcknowledgeMessages().size(), equalTo(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void assertNotEmptyAcknowledgeMessages(StartBasicResponse response) {
|
||||||
|
assertThat(response.getAcknowledgeMessages().entrySet(), not(empty()));
|
||||||
|
for (Map.Entry<String, String[]> entry : response.getAcknowledgeMessages().entrySet()) {
|
||||||
|
assertThat(entry.getKey(), not(isEmptyOrNullString()));
|
||||||
|
final List<String> messages = Arrays.asList(entry.getValue());
|
||||||
|
for (String message : messages) {
|
||||||
|
assertThat(message, not(isEmptyOrNullString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1572,6 +1572,12 @@ public class RequestConvertersTests extends ESTestCase {
|
||||||
setRandomLocal(request::local, expectedParams);
|
setRandomLocal(request::local, expectedParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setRandomTimeout(TimedRequest request, TimeValue defaultTimeout, Map<String, String> expectedParams) {
|
||||||
|
setRandomTimeout(s ->
|
||||||
|
request.setTimeout(TimeValue.parseTimeValue(s, request.getClass().getName() + ".timeout")),
|
||||||
|
defaultTimeout, expectedParams);
|
||||||
|
}
|
||||||
|
|
||||||
static void setRandomTimeout(Consumer<String> setter, TimeValue defaultTimeout, Map<String, String> expectedParams) {
|
static void setRandomTimeout(Consumer<String> setter, TimeValue defaultTimeout, Map<String, String> expectedParams) {
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
String timeout = randomTimeValue();
|
String timeout = randomTimeValue();
|
||||||
|
@ -1583,9 +1589,19 @@ public class RequestConvertersTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setRandomMasterTimeout(MasterNodeRequest<?> request, Map<String, String> expectedParams) {
|
static void setRandomMasterTimeout(MasterNodeRequest<?> request, Map<String, String> expectedParams) {
|
||||||
|
setRandomMasterTimeout(request::masterNodeTimeout, expectedParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setRandomMasterTimeout(TimedRequest request, Map<String, String> expectedParams) {
|
||||||
|
setRandomMasterTimeout(s ->
|
||||||
|
request.setMasterTimeout(TimeValue.parseTimeValue(s, request.getClass().getName() + ".masterNodeTimeout")),
|
||||||
|
expectedParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setRandomMasterTimeout(Consumer<String> setter, Map<String, String> expectedParams) {
|
||||||
if (randomBoolean()) {
|
if (randomBoolean()) {
|
||||||
String masterTimeout = randomTimeValue();
|
String masterTimeout = randomTimeValue();
|
||||||
request.masterNodeTimeout(masterTimeout);
|
setter.accept(masterTimeout);
|
||||||
expectedParams.put("master_timeout", masterTimeout);
|
expectedParams.put("master_timeout", masterTimeout);
|
||||||
} else {
|
} else {
|
||||||
expectedParams.put("master_timeout", MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT.getStringRep());
|
expectedParams.put("master_timeout", MasterNodeRequest.DEFAULT_MASTER_NODE_TIMEOUT.getStringRep());
|
||||||
|
|
|
@ -26,6 +26,8 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
|
||||||
import org.elasticsearch.client.RequestOptions;
|
import org.elasticsearch.client.RequestOptions;
|
||||||
import org.elasticsearch.client.RestHighLevelClient;
|
import org.elasticsearch.client.RestHighLevelClient;
|
||||||
|
import org.elasticsearch.client.license.StartBasicRequest;
|
||||||
|
import org.elasticsearch.client.license.StartBasicResponse;
|
||||||
import org.elasticsearch.common.Booleans;
|
import org.elasticsearch.common.Booleans;
|
||||||
import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
|
import org.elasticsearch.protocol.xpack.license.DeleteLicenseRequest;
|
||||||
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
|
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
|
||||||
|
@ -33,11 +35,15 @@ import org.elasticsearch.protocol.xpack.license.GetLicenseResponse;
|
||||||
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
|
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
|
||||||
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
|
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
|
||||||
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
|
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static org.elasticsearch.client.LicensingIT.putTrialLicense;
|
||||||
import static org.hamcrest.Matchers.containsString;
|
import static org.hamcrest.Matchers.containsString;
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.hamcrest.Matchers.hasSize;
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
@ -50,8 +56,18 @@ import static org.hamcrest.Matchers.startsWith;
|
||||||
*/
|
*/
|
||||||
public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {
|
public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void checkForSnapshot() {
|
||||||
|
assumeTrue("Trial license used to rollback is only valid when tested against snapshot/test builds",
|
||||||
|
Build.CURRENT.isSnapshot());
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void rollbackToTrial() throws IOException {
|
||||||
|
putTrialLicense();
|
||||||
|
}
|
||||||
|
|
||||||
public void testLicense() throws Exception {
|
public void testLicense() throws Exception {
|
||||||
assumeTrue("License is only valid when tested against snapshot/test builds", Build.CURRENT.isSnapshot());
|
|
||||||
RestHighLevelClient client = highLevelClient();
|
RestHighLevelClient client = highLevelClient();
|
||||||
String license = "{\"license\": {\"uid\":\"893361dc-9749-4997-93cb-802e3d7fa4a8\",\"type\":\"gold\"," +
|
String license = "{\"license\": {\"uid\":\"893361dc-9749-4997-93cb-802e3d7fa4a8\",\"type\":\"gold\"," +
|
||||||
"\"issue_date_in_millis\":1411948800000,\"expiry_date_in_millis\":1914278399999,\"max_nodes\":1,\"issued_to\":\"issued_to\"," +
|
"\"issue_date_in_millis\":1411948800000,\"expiry_date_in_millis\":1914278399999,\"max_nodes\":1,\"issued_to\":\"issued_to\"," +
|
||||||
|
@ -215,4 +231,50 @@ public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {
|
||||||
assertThat(currentLicense, endsWith("}"));
|
assertThat(currentLicense, endsWith("}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testPostStartBasic() throws Exception {
|
||||||
|
RestHighLevelClient client = highLevelClient();
|
||||||
|
{
|
||||||
|
//tag::start-basic-execute
|
||||||
|
StartBasicRequest request = new StartBasicRequest();
|
||||||
|
|
||||||
|
StartBasicResponse response = client.license().startBasic(request, RequestOptions.DEFAULT);
|
||||||
|
//end::start-basic-execute
|
||||||
|
|
||||||
|
//tag::start-basic-response
|
||||||
|
boolean acknowledged = response.isAcknowledged(); // <1>
|
||||||
|
boolean basicStarted = response.isBasicStarted(); // <2>
|
||||||
|
String errorMessage = response.getErrorMessage(); // <3>
|
||||||
|
String acknowledgeMessage = response.getAcknowledgeMessage(); // <4>
|
||||||
|
Map<String, String[]> acknowledgeMessages = response.getAcknowledgeMessages(); // <5>
|
||||||
|
//end::start-basic-response
|
||||||
|
}
|
||||||
|
{
|
||||||
|
StartBasicRequest request = new StartBasicRequest();
|
||||||
|
// tag::start-basic-listener
|
||||||
|
ActionListener<StartBasicResponse> listener = new ActionListener<StartBasicResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(StartBasicResponse indexResponse) {
|
||||||
|
// <1>
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Exception e) {
|
||||||
|
// <2>
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// end::start-basic-listener
|
||||||
|
|
||||||
|
// Replace the empty listener by a blocking listener in test
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
listener = new LatchedActionListener<>(listener, latch);
|
||||||
|
|
||||||
|
// tag::start-basic-execute-async
|
||||||
|
client.license().startBasicAsync(
|
||||||
|
request, RequestOptions.DEFAULT, listener); // <1>
|
||||||
|
// end::start-basic-execute-async
|
||||||
|
|
||||||
|
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* 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.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
|
import org.elasticsearch.protocol.xpack.common.ProtocolUtils;
|
||||||
|
import org.elasticsearch.test.ESTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
|
||||||
|
public class StartBasicResponseTests extends ESTestCase {
|
||||||
|
|
||||||
|
public void testFromXContent() throws Exception {
|
||||||
|
StartBasicResponse.Status status = randomFrom(StartBasicResponse.Status.values());
|
||||||
|
|
||||||
|
boolean acknowledged = status != StartBasicResponse.Status.NEED_ACKNOWLEDGEMENT;
|
||||||
|
String acknowledgeMessage = null;
|
||||||
|
Map<String, String[]> ackMessages = Collections.emptyMap();
|
||||||
|
if (status != StartBasicResponse.Status.GENERATED_BASIC) {
|
||||||
|
acknowledgeMessage = randomAlphaOfLength(10);
|
||||||
|
ackMessages = randomAckMessages();
|
||||||
|
}
|
||||||
|
|
||||||
|
final StartBasicResponse startBasicResponse = new StartBasicResponse(status, ackMessages, acknowledgeMessage);
|
||||||
|
|
||||||
|
XContentType xContentType = randomFrom(XContentType.values());
|
||||||
|
XContentBuilder builder = XContentFactory.contentBuilder(xContentType);
|
||||||
|
|
||||||
|
toXContent(startBasicResponse, builder);
|
||||||
|
|
||||||
|
final StartBasicResponse response = StartBasicResponse.fromXContent(createParser(builder));
|
||||||
|
assertThat(response.isAcknowledged(), equalTo(acknowledged));
|
||||||
|
assertThat(response.isBasicStarted(), equalTo(status.isBasicStarted()));
|
||||||
|
assertThat(response.getAcknowledgeMessage(), equalTo(acknowledgeMessage));
|
||||||
|
assertThat(ProtocolUtils.equals(response.getAcknowledgeMessages(), ackMessages), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void toXContent(StartBasicResponse response, XContentBuilder builder) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
builder.field("acknowledged", response.isAcknowledged());
|
||||||
|
if (response.isBasicStarted()) {
|
||||||
|
builder.field("basic_was_started", true);
|
||||||
|
} else {
|
||||||
|
builder.field("basic_was_started", false);
|
||||||
|
builder.field("error_message", response.getErrorMessage());
|
||||||
|
}
|
||||||
|
if (response.getAcknowledgeMessages().isEmpty() == false) {
|
||||||
|
builder.startObject("acknowledge");
|
||||||
|
builder.field("message", response.getAcknowledgeMessage());
|
||||||
|
for (Map.Entry<String, String[]> entry : response.getAcknowledgeMessages().entrySet()) {
|
||||||
|
builder.startArray(entry.getKey());
|
||||||
|
for (String message : entry.getValue()) {
|
||||||
|
builder.value(message);
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, String[]> randomAckMessages() {
|
||||||
|
int nFeatures = randomIntBetween(1, 5);
|
||||||
|
|
||||||
|
Map<String, String[]> ackMessages = new HashMap<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < nFeatures; i++) {
|
||||||
|
String feature = randomAlphaOfLengthBetween(9, 15);
|
||||||
|
int nMessages = randomIntBetween(1, 5);
|
||||||
|
String[] messages = new String[nMessages];
|
||||||
|
for (int j = 0; j < nMessages; j++) {
|
||||||
|
messages[j] = randomAlphaOfLengthBetween(10, 30);
|
||||||
|
}
|
||||||
|
ackMessages.put(feature, messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ackMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
[[java-rest-high-start-basic]]
|
||||||
|
=== Start Basic License
|
||||||
|
|
||||||
|
[[java-rest-high-start-basic-execution]]
|
||||||
|
==== Execution
|
||||||
|
|
||||||
|
This API creates and enables a basic license using the `startBasic()` method.
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-basic-execute]
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
[[java-rest-high-start-basic-response]]
|
||||||
|
==== Response
|
||||||
|
|
||||||
|
The returned `StartBasicResponse` returns a field indicating whether the
|
||||||
|
basic 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-basic-response]
|
||||||
|
--------------------------------------------------
|
||||||
|
<1> Whether or not the request had the `acknowledge` flag set
|
||||||
|
<2> Whether or not this request caused a basic to start
|
||||||
|
<3> If this request did not cause a basic to start, a message explaining why
|
||||||
|
<4> If the user's request did not have the `acknowledge` flag set, a summary
|
||||||
|
of the user's acknowledgement required for this API
|
||||||
|
<5> 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 basic
|
||||||
|
|
||||||
|
[[java-rest-high-start-basic-async]]
|
||||||
|
==== Asynchronous Execution
|
||||||
|
|
||||||
|
This request can be executed asynchronously:
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-basic-execute-async]
|
||||||
|
--------------------------------------------------
|
||||||
|
<1> The `StartBasicResponse` to execute and the `ActionListener` to use when
|
||||||
|
the execution completes
|
||||||
|
|
||||||
|
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 `StartBasicResponse` looks like:
|
||||||
|
|
||||||
|
["source","java",subs="attributes,callouts,macros"]
|
||||||
|
--------------------------------------------------
|
||||||
|
include-tagged::{doc-tests}/LicensingDocumentationIT.java[start-basic-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
|
|
@ -214,10 +214,12 @@ The Java High Level REST Client supports the following Licensing APIs:
|
||||||
* <<java-rest-high-put-license>>
|
* <<java-rest-high-put-license>>
|
||||||
* <<java-rest-high-get-license>>
|
* <<java-rest-high-get-license>>
|
||||||
* <<java-rest-high-delete-license>>
|
* <<java-rest-high-delete-license>>
|
||||||
|
* <<java-rest-high-start-basic>>
|
||||||
|
|
||||||
include::licensing/put-license.asciidoc[]
|
include::licensing/put-license.asciidoc[]
|
||||||
include::licensing/get-license.asciidoc[]
|
include::licensing/get-license.asciidoc[]
|
||||||
include::licensing/delete-license.asciidoc[]
|
include::licensing/delete-license.asciidoc[]
|
||||||
|
include::licensing/start-basic.asciidoc[]
|
||||||
|
|
||||||
== Machine Learning APIs
|
== Machine Learning APIs
|
||||||
:upid: {mainid}-x-pack-ml
|
:upid: {mainid}-x-pack-ml
|
||||||
|
|
Loading…
Reference in New Issue