diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java index df7b37d3e6b..f21d7f02014 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/LicenseService.java @@ -14,7 +14,6 @@ import org.elasticsearch.cluster.AckedClusterStateUpdateTask; import org.elasticsearch.cluster.ClusterChangedEvent; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterStateListener; -import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; @@ -343,29 +342,10 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste /** * Remove license from the cluster state metadata */ - public void removeLicense(final DeleteLicenseRequest request, final ActionListener listener) { + public void removeLicense(final DeleteLicenseRequest request, final ActionListener listener) { + final PostStartBasicRequest startBasicRequest = new PostStartBasicRequest().acknowledge(true); clusterService.submitStateUpdateTask("delete license", - new AckedClusterStateUpdateTask(request, listener) { - @Override - protected ClusterStateUpdateResponse newResponse(boolean acknowledged) { - return new ClusterStateUpdateResponse(acknowledged); - } - - @Override - public ClusterState execute(ClusterState currentState) throws Exception { - MetaData metaData = currentState.metaData(); - final LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE); - if (currentLicenses.getLicense() != LicensesMetaData.LICENSE_TOMBSTONE) { - MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); - LicensesMetaData newMetadata = new LicensesMetaData(LicensesMetaData.LICENSE_TOMBSTONE, - currentLicenses.getMostRecentTrialVersion()); - mdBuilder.putCustom(LicensesMetaData.TYPE, newMetadata); - return ClusterState.builder(currentState).metaData(mdBuilder).build(); - } else { - return currentState; - } - } - }); + new StartBasicClusterTask(logger, clusterService.getClusterName().value(), clock, startBasicRequest, listener)); } public License getLicense() { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartBasicClusterTask.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartBasicClusterTask.java index 3c6c00a5f86..1846c9f3260 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartBasicClusterTask.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/StartBasicClusterTask.java @@ -61,19 +61,10 @@ public class StartBasicClusterTask extends ClusterStateUpdateTask { @Override public ClusterState execute(ClusterState currentState) throws Exception { XPackPlugin.checkReadyForXPackCustomMetadata(currentState); - LicensesMetaData licensesMetaData = currentState.metaData().custom(LicensesMetaData.TYPE); - License currentLicense = LicensesMetaData.extractLicense(licensesMetaData); - if (currentLicense == null || License.LicenseType.isBasic(currentLicense.type()) == false) { - long issueDate = clock.millis(); - MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); - License.Builder specBuilder = License.builder() - .uid(UUID.randomUUID().toString()) - .issuedTo(clusterName) - .maxNodes(LicenseService.SELF_GENERATED_LICENSE_MAX_NODES) - .issueDate(issueDate) - .type(License.LicenseType.BASIC) - .expiryDate(LicenseService.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS); - License selfGeneratedLicense = SelfGeneratedLicense.create(specBuilder, currentState.nodes()); + LicensesMetaData currentLicensesMetaData = currentState.metaData().custom(LicensesMetaData.TYPE); + License currentLicense = LicensesMetaData.extractLicense(currentLicensesMetaData); + if (shouldGenerateNewBasicLicense(currentLicense)) { + License selfGeneratedLicense = generateBasicLicense(currentState); if (request.isAcknowledged() == false && currentLicense != null) { Map ackMessages = LicenseService.getAckMessages(selfGeneratedLicense, currentLicense); if (ackMessages.isEmpty() == false) { @@ -81,11 +72,9 @@ public class StartBasicClusterTask extends ClusterStateUpdateTask { return currentState; } } - Version trialVersion = null; - if (licensesMetaData != null) { - trialVersion = licensesMetaData.getMostRecentTrialVersion(); - } + Version trialVersion = currentLicensesMetaData != null ? currentLicensesMetaData.getMostRecentTrialVersion() : null; LicensesMetaData newLicensesMetaData = new LicensesMetaData(selfGeneratedLicense, trialVersion); + MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData()); mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData); return ClusterState.builder(currentState).metaData(mdBuilder).build(); } else { @@ -98,4 +87,23 @@ public class StartBasicClusterTask extends ClusterStateUpdateTask { logger.error(new ParameterizedMessage("unexpected failure during [{}]", source), e); listener.onFailure(e); } + + private boolean shouldGenerateNewBasicLicense(License currentLicense) { + return currentLicense == null + || License.LicenseType.isBasic(currentLicense.type()) == false + || LicenseService.SELF_GENERATED_LICENSE_MAX_NODES != currentLicense.maxNodes() + || LicenseService.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS != currentLicense.expiryDate(); + } + + private License generateBasicLicense(ClusterState currentState) { + final License.Builder specBuilder = License.builder() + .uid(UUID.randomUUID().toString()) + .issuedTo(clusterName) + .maxNodes(LicenseService.SELF_GENERATED_LICENSE_MAX_NODES) + .issueDate(clock.millis()) + .type(License.LicenseType.BASIC) + .expiryDate(LicenseService.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS); + + return SelfGeneratedLicense.create(specBuilder, currentState.nodes()); + } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java index f47a14e05bb..b360c219238 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/license/TransportDeleteLicenseAction.java @@ -11,7 +11,6 @@ import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.support.master.TransportMasterNodeAction; import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.block.ClusterBlockException; import org.elasticsearch.cluster.block.ClusterBlockLevel; import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver; @@ -55,10 +54,10 @@ public class TransportDeleteLicenseAction extends TransportMasterNodeAction listener) throws ElasticsearchException { - licenseService.removeLicense(request, new ActionListener() { + licenseService.removeLicense(request, new ActionListener() { @Override - public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { - listener.onResponse(new AcknowledgedResponse(clusterStateUpdateResponse.isAcknowledged())); + public void onResponse(PostStartBasicResponse postStartBasicResponse) { + listener.onResponse(new AcknowledgedResponse(postStartBasicResponse.isAcknowledged())); } @Override diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicenseServiceClusterTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicenseServiceClusterTests.java index 2e79073af2c..033f004725c 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicenseServiceClusterTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicenseServiceClusterTests.java @@ -23,7 +23,6 @@ import java.util.Collection; import static org.elasticsearch.test.ESIntegTestCase.Scope.TEST; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.nullValue; @ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0, maxNumDataNodes = 0, transportClientRatio = 0) public class LicenseServiceClusterTests extends AbstractLicensesIntegrationTestCase { @@ -78,14 +77,14 @@ public class LicenseServiceClusterTests extends AbstractLicensesIntegrationTestC assertThat(licensingClient.prepareGetLicense().get().license(), equalTo(license)); logger.info("--> remove licenses"); licensingClient.prepareDeleteLicense().get(); - assertOperationMode(License.OperationMode.MISSING); + assertOperationMode(License.OperationMode.BASIC); logger.info("--> restart all nodes"); internalCluster().fullRestart(); licensingClient = new LicensingClient(client()); ensureYellow(); - assertThat(licensingClient.prepareGetLicense().get().license(), nullValue()); - assertOperationMode(License.OperationMode.MISSING); + assertTrue(License.LicenseType.isBasic(licensingClient.prepareGetLicense().get().license().type())); + assertOperationMode(License.OperationMode.BASIC); wipeAllLicenses(); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesManagerServiceTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesManagerServiceTests.java index f3fbab1026e..2e8ecbcde33 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesManagerServiceTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesManagerServiceTests.java @@ -6,7 +6,6 @@ package org.elasticsearch.license; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; @@ -120,16 +119,16 @@ public class LicensesManagerServiceTests extends ESSingleNodeTestCase { // remove signed licenses removeAndAckSignedLicenses(licenseService); licensesMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE); - assertThat(licensesMetaData.getLicense(), equalTo(LicensesMetaData.LICENSE_TOMBSTONE)); + assertTrue(License.LicenseType.isBasic(licensesMetaData.getLicense().type())); } private void removeAndAckSignedLicenses(final LicenseService licenseService) { final CountDownLatch latch = new CountDownLatch(1); final AtomicBoolean success = new AtomicBoolean(false); - licenseService.removeLicense(new DeleteLicenseRequest(), new ActionListener() { + licenseService.removeLicense(new DeleteLicenseRequest(), new ActionListener() { @Override - public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) { - if (clusterStateUpdateResponse.isAcknowledged()) { + public void onResponse(PostStartBasicResponse postStartBasicResponse) { + if (postStartBasicResponse.isAcknowledged()) { success.set(true); } latch.countDown(); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java index abaa7e1c5d3..244c982bc21 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/LicensesTransportTests.java @@ -187,7 +187,7 @@ public class LicensesTransportTests extends ESSingleNodeTestCase { assertThat(deleteLicenseResponse.isAcknowledged(), equalTo(true)); // get licenses (expected no licenses) getLicenseResponse = new GetLicenseRequestBuilder(client().admin().cluster(), GetLicenseAction.INSTANCE).get(); - assertNull(getLicenseResponse.license()); + assertTrue(License.LicenseType.isBasic(getLicenseResponse.license().type())); } public void testLicenseIsRejectWhenStartDateLaterThanNow() throws Exception { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartBasicLicenseTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartBasicLicenseTests.java index 1b7d889d726..2839e07e53c 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartBasicLicenseTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartBasicLicenseTests.java @@ -61,12 +61,6 @@ public class StartBasicLicenseTests extends AbstractLicensesIntegrationTestCase assertEquals("trial", getLicenseResponse.license().type()); }); - // Testing that you can start a basic license when you have no license - if (randomBoolean()) { - licensingClient.prepareDeleteLicense().get(); - assertNull(licensingClient.prepareGetLicense().get().license()); - } - RestClient restClient = getRestClient(); Response response = restClient.performRequest(new Request("GET", "/_license/basic_status")); String body = Streams.copyToString(new InputStreamReader(response.getEntity().getContent(), StandardCharsets.UTF_8)); diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml index 78f507c6b3a..28f21b3ad5c 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml @@ -66,7 +66,7 @@ teardown: - length: { license: 11 } - match: { license.uid: "893361dc-9749-4997-93cb-802e3dofh7aa" } --- -"Should throw 404 after license deletion": +"Should revert back to basic license after license deletion": - do: license.delete: {} @@ -74,7 +74,15 @@ teardown: - do: license.get: {} - catch: missing + + - match: { license.type: "basic" } + - set: { license.uid: id } + + - do: # delete an existing basic license is a no-op + license.delete: {} + - do: + license.get: {} + - match: { license.uid: $id} --- "Should install a feature type license":