瀏覽代碼

License removal leads back to a basic license (#52407)

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
Yang Wang 5 年之前
父節點
當前提交
0d62213ca4

+ 3 - 23
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;
@@ -340,29 +339,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() {

+ 25 - 17
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<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());
+    }
 }

+ 3 - 4
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;
@@ -56,10 +55,10 @@ public class TransportDeleteLicenseAction extends TransportMasterNodeAction<Dele
     @Override
     protected void masterOperation(Task task, 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

+ 3 - 4
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)
 public class LicenseServiceClusterTests extends AbstractLicensesIntegrationTestCase {
@@ -73,14 +72,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();

+ 4 - 5
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<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();

+ 1 - 1
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 {

+ 0 - 6
x-pack/plugin/core/src/test/java/org/elasticsearch/license/StartBasicLicenseTests.java

@@ -55,12 +55,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));

+ 10 - 2
x-pack/plugin/src/test/resources/rest-api-spec/test/license/20_put_license.yml

@@ -66,7 +66,7 @@ teardown:
   - length: { license: 12 }
   - 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":