Skip to content

Commit

Permalink
Rest HL client: Add put license action
Browse files Browse the repository at this point in the history
  • Loading branch information
imotov committed Jul 19, 2018
1 parent 9ae6905 commit da77fc5
Show file tree
Hide file tree
Showing 25 changed files with 881 additions and 258 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.action.ActionListener;
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;

import java.io.IOException;

import static java.util.Collections.emptySet;

/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for
* accessing the Elastic License-related methods
* <p>
* See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/licensing-apis.html">
* X-Pack Licensing APIs on elastic.co</a> for more information.
*/
public class LicenseClient {

private final RestHighLevelClient restHighLevelClient;

LicenseClient(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
}

/**
* Updates license for 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 PutLicenseResponse putLicense(PutLicenseRequest request, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::putLicense, options,
PutLicenseResponse::fromXContent, emptySet());
}

/**
* Asynchronously updates license for the cluster 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 putLicenseAsync(PutLicenseRequest request, RequestOptions options, ActionListener<PutLicenseResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::putLicense, options,
PutLicenseResponse::fromXContent, listener, emptySet());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
import org.elasticsearch.rest.action.search.RestSearchAction;
import org.elasticsearch.script.mustache.MultiSearchTemplateRequest;
import org.elasticsearch.script.mustache.SearchTemplateRequest;
Expand Down Expand Up @@ -1124,6 +1125,18 @@ static Request xpackUsage(XPackUsageRequest usageRequest) {
return request;
}

static Request putLicense(PutLicenseRequest putLicenseRequest) {
Request request = new Request(HttpPut.METHOD_NAME, "/_xpack/license");
Params parameters = new Params(request);
parameters.withTimeout(putLicenseRequest.timeout());
parameters.withMasterTimeout(putLicenseRequest.masterNodeTimeout());
if (putLicenseRequest.isAcknowledge()) {
parameters.putParam("acknowledge", "true");
}
request.setJsonEntity(putLicenseRequest.getLicenseDefinition());
return request;
}

private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef();
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ public final class XPackClient {

private final RestHighLevelClient restHighLevelClient;
private final WatcherClient watcherClient;
private final LicenseClient licenseClient;

XPackClient(RestHighLevelClient restHighLevelClient) {
this.restHighLevelClient = restHighLevelClient;
this.watcherClient = new WatcherClient(restHighLevelClient);
this.licenseClient = new LicenseClient(restHighLevelClient);
}

public WatcherClient watcher() {
Expand Down Expand Up @@ -100,4 +102,15 @@ public void usageAsync(XPackUsageRequest request, RequestOptions options, Action
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::xpackUsage, options,
XPackUsageResponse::fromXContent, listener, emptySet());
}

/**
* A wrapper for the {@link RestHighLevelClient} that provides methods for
* accessing the Elastic Licensing APIs.
* <p>
* See the <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/licensing-apis.html">
* X-Pack APIs on elastic.co</a> for more information.
*/
public LicenseClient license() {
return licenseClient;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* 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.documentation;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.LatchedActionListener;
import org.elasticsearch.client.ESRestHighLevelClientTestCase;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;

import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.startsWith;

/**
* Documentation for Licensing APIs in the high level java client.
* Code wrapped in {@code tag} and {@code end} tags is included in the docs.
*/
public class LicensingDocumentationIT extends ESRestHighLevelClientTestCase {

public void testPutLicense() throws Exception {
RestHighLevelClient client = highLevelClient();
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\"," +
"\"issuer\":\"issuer\",\"signature\":\"AAAAAgAAAA3U8+YmnvwC+CWsV/mRAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSm" +
"kxakxZdW5IMlhlTHNoN1N2MXMvRFk4d3JTZEx3R3RRZ0pzU3lobWJKZnQvSEFva0ppTHBkWkprZWZSQi9iNmRQNkw1SlpLN0lDalZCS095MXRGN1lIZlpYcVVTTn" +
"FrcTE2dzhJZmZrdFQrN3JQeGwxb0U0MXZ0dDJHSERiZTVLOHNzSDByWnpoZEphZHBEZjUrTVBxRENNSXNsWWJjZllaODdzVmEzUjNiWktNWGM5TUhQV2plaUo4Q1" +
"JOUml4MXNuL0pSOEhQaVB2azhmUk9QVzhFeTFoM1Q0RnJXSG53MWk2K055c28zSmRnVkF1b2JSQkFLV2VXUmVHNDZ2R3o2VE1qbVNQS2lxOHN5bUErZlNIWkZSVm" +
"ZIWEtaSU9wTTJENDVvT1NCYklacUYyK2FwRW9xa0t6dldMbmMzSGtQc3FWOTgzZ3ZUcXMvQkt2RUZwMFJnZzlvL2d2bDRWUzh6UG5pdENGWFRreXNKNkE9PQAAAQ" +
"Be8GfzDm6T537Iuuvjetb3xK5dvg0K5NQapv+rczWcQFxgCuzbF8plkgetP1aAGZP4uRESDQPMlOCsx4d0UqqAm9f7GbBQ3l93P+PogInPFeEH9NvOmaAQovmxVM" +
"9SE6DsDqlX4cXSO+bgWpXPTd2LmpoQc1fXd6BZ8GeuyYpVHVKp9hVU0tAYjw6HzYOE7+zuO1oJYOxElqy66AnIfkvHrvni+flym3tE7tDTgsDRaz7W3iBhaqiSnt" +
"EqabEkvHdPHQdSR99XGaEvnHO1paK01/35iZF6OXHsF7CCj+558GRXiVxzueOe7TsGSSt8g7YjZwV9bRCyU7oB4B/nidgI\"}}";
{
//tag::put-license-execute
PutLicenseRequest request = new PutLicenseRequest();
request.setLicenseDefinition(license); // <1>
request.setAcknowledge(false); // <2>

PutLicenseResponse response = client.xpack().license().putLicense(request, RequestOptions.DEFAULT);
//end::put-license-execute

//tag::put-license-response
LicensesStatus status = response.status(); // <1>
assertEquals(status, LicensesStatus.VALID); // <2>
boolean acknowledged = response.isAcknowledged(); // <3>
String acknowledgeHeader = response.acknowledgeHeader(); // <4>
Map<String, String[]> acknowledgeMessages = response.acknowledgeMessages(); // <5>
//end::put-license-response

assertFalse(acknowledged); // Should fail because we are trying to downgrade from platinum trial to gold
assertThat(acknowledgeHeader, startsWith("This license update requires acknowledgement."));
assertThat(acknowledgeMessages.keySet(), not(hasSize(0)));
}
{
PutLicenseRequest request = new PutLicenseRequest();
// tag::put-license-execute-listener
ActionListener<PutLicenseResponse> listener = new ActionListener<PutLicenseResponse>() {
@Override
public void onResponse(PutLicenseResponse indexResponse) {
// <1>
}

@Override
public void onFailure(Exception e) {
// <2>
}
};
// end::put-license-execute-listener

// Replace the empty listener by a blocking listener in test
final CountDownLatch latch = new CountDownLatch(1);
listener = new LatchedActionListener<>(listener, latch);

// tag::put-license-execute-async
client.xpack().license().putLicenseAsync(
request, RequestOptions.DEFAULT, listener); // <1>
// end::put-license-execute-async

assertTrue(latch.await(30L, TimeUnit.SECONDS));
}
}
}
64 changes: 64 additions & 0 deletions docs/java-rest/high-level/licensing/put-license.asciidoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
[[java-rest-high-put-license]]
=== Update License

[[java-rest-high-put-license-execution]]
==== Execution

The license can be added or updated using the `putLicense()` method:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[put-license-execute]
--------------------------------------------------
<1> Set the categories of information to retrieve. The the default is to
return no information which is useful for checking if {xpack} is installed
but not much else.
<2> A JSON document containing the license information.

[[java-rest-high-put-license-response]]
==== Response

The returned `PutLicenseResponse` contains the `LicensesStatus`,
`acknowledged` flag and possible acknowledge messages. The acknowledge messages
are present if you previously had a license with more features than one you
are trying to update and you didn't set the `acknowledge` flag to `true`. In this case
you need to display the messages to the end user and if they agree, resubmit the
license with the `acknowledge` flag set to `true`.

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[put-license-response]
--------------------------------------------------
<1> The status of the license
<2> Make sure that the license is valid.
<3> Check the acknowledge flag.
<4> It should be true if license is acknowledge.
<5> Otherwise we can see the acknowledge messages in `acknowledgeHeader()`
<6> and check component-specific messages in `acknowledgeMessages()`.

[[java-rest-high-put-license-async]]
==== Asynchronous Execution

This request can be executed asynchronously:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[put-license-execute-async]
--------------------------------------------------
<1> The `PutLicenseRequest` 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 `PutLicenseResponse` looks like:

["source","java",subs="attributes,callouts,macros"]
--------------------------------------------------
include-tagged::{doc-tests}/LicensingDocumentationIT.java[put-license-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
9 changes: 9 additions & 0 deletions docs/java-rest/high-level/supported-apis.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,12 @@ The Java High Level REST Client supports the following Scripts APIs:

include::script/get_script.asciidoc[]
include::script/delete_script.asciidoc[]


== Licensing APIs

The Java High Level REST Client supports the following Licensing APIs:

* <<java-rest-high-put-license>>

include::licensing/put-license.asciidoc[]
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import org.elasticsearch.env.Environment;
import org.elasticsearch.gateway.GatewayService;
import org.elasticsearch.protocol.xpack.XPackInfoResponse;
import org.elasticsearch.protocol.xpack.license.LicensesStatus;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.client.ElasticsearchClient;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;

public class LicensingClient {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package org.elasticsearch.license;

import org.elasticsearch.action.Action;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;

public class PutLicenseAction extends Action<PutLicenseResponse> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.elasticsearch.client.ElasticsearchClient;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.protocol.xpack.license.PutLicenseResponse;

/**
* Register license request builder
Expand Down
Loading

0 comments on commit da77fc5

Please sign in to comment.