A new basic license will be generated when existing license is deleted. In addition, deleting an existing basic license is a no-op. Resolves: #45022
This commit is contained in:
parent
d26d7721ea
commit
7cefba78c5
|
@ -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<ClusterStateUpdateResponse> listener) {
|
||||
public void removeLicense(final DeleteLicenseRequest request, final ActionListener<PostStartBasicResponse> listener) {
|
||||
final PostStartBasicRequest startBasicRequest = new PostStartBasicRequest().acknowledge(true);
|
||||
clusterService.submitStateUpdateTask("delete license",
|
||||
new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(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() {
|
||||
|
|
|
@ -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<String, String[]> 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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Dele
|
|||
@Override
|
||||
protected void masterOperation(final DeleteLicenseRequest request, ClusterState state, final ActionListener<AcknowledgedResponse>
|
||||
listener) throws ElasticsearchException {
|
||||
licenseService.removeLicense(request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
licenseService.removeLicense(request, new ActionListener<PostStartBasicResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
|
||||
listener.onResponse(new AcknowledgedResponse(clusterStateUpdateResponse.isAcknowledged()));
|
||||
public void onResponse(PostStartBasicResponse postStartBasicResponse) {
|
||||
listener.onResponse(new AcknowledgedResponse(postStartBasicResponse.isAcknowledged()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<ClusterStateUpdateResponse>() {
|
||||
licenseService.removeLicense(new DeleteLicenseRequest(), new ActionListener<PostStartBasicResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
|
||||
if (clusterStateUpdateResponse.isAcknowledged()) {
|
||||
public void onResponse(PostStartBasicResponse postStartBasicResponse) {
|
||||
if (postStartBasicResponse.isAcknowledged()) {
|
||||
success.set(true);
|
||||
}
|
||||
latch.countDown();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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":
|
||||
|
|
Loading…
Reference in New Issue