- Fix test concurrency bugs
- Minor test fixes - LicensesService documentation Original commit: elastic/x-pack-elasticsearch@ab98ba8a2d
This commit is contained in:
parent
93944f27f2
commit
3aec0fd1f0
|
@ -46,15 +46,19 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
import static org.elasticsearch.license.core.ESLicenses.reduceAndMap;
|
||||
|
||||
/**
|
||||
* Service responsible for managing {@link org.elasticsearch.license.plugin.core.LicensesMetaData}
|
||||
* Service responsible for managing {@link LicensesMetaData}
|
||||
* Interfaces through which this is exposed are:
|
||||
* - LicensesManagerService - responsible for managing signed and one-time-trial licenses
|
||||
* - LicensesClientService - responsible for feature registration and notification to consumer plugin(s)
|
||||
*
|
||||
* <p/>
|
||||
* Registration Scheme:
|
||||
* <p/>
|
||||
* A consumer plugin (feature) is registered with {@link LicensesClientService#register(String, TrialLicenseOptions, LicensesClientService.Listener)}
|
||||
* This method can be called at any time during the life-cycle of the consumer plugin.
|
||||
*
|
||||
* If the feature can not be registered immediately, it is queued up and registered on the first clusterChanged event with
|
||||
* no {@link GatewayService#STATE_NOT_RECOVERED_BLOCK} block
|
||||
* Upon successful registration, the feature(s) are notified appropriately using the notification scheme
|
||||
*
|
||||
* <p/>
|
||||
* Notification Scheme:
|
||||
|
@ -69,7 +73,7 @@ import static org.elasticsearch.license.core.ESLicenses.reduceAndMap;
|
|||
* <p/>
|
||||
* The {@link LicensingClientNotificationJob} calls {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} to schedule
|
||||
* another delayed {@link LicensingClientNotificationJob} as stated above. It is a no-op in case of a global block on
|
||||
* {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
* {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
* <p/>
|
||||
* Upon successful registration of a new feature:
|
||||
* - {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} is called
|
||||
|
@ -78,8 +82,8 @@ import static org.elasticsearch.license.core.ESLicenses.reduceAndMap;
|
|||
* - {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)} is called if:
|
||||
* - new trial/signed license(s) are found in the cluster state meta data
|
||||
* - if new feature(s) are added to the registeredListener
|
||||
* - if the previous cluster state had a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
* - no-op in case of global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
* - if the previous cluster state had a global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
* - no-op in case of global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
*/
|
||||
@Singleton
|
||||
public class LicensesService extends AbstractLifecycleComponent<LicensesService> implements ClusterStateListener, LicensesManagerService, LicensesClientService {
|
||||
|
@ -380,10 +384,10 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
}
|
||||
|
||||
/**
|
||||
* When there is no global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}:
|
||||
* When there is no global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}:
|
||||
* - tries to register any {@link #pendingListeners} by calling {@link #registeredListeners}
|
||||
* - if any {@link #pendingListeners} are registered successfully or if previous cluster state had a block on
|
||||
* {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}, calls
|
||||
* {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}, calls
|
||||
* {@link #notifyFeaturesAndScheduleNotification(LicensesMetaData)}
|
||||
* - else calls {@link #notifyFeaturesAndScheduleNotificationIfNeeded(LicensesMetaData)}
|
||||
*/
|
||||
|
@ -435,6 +439,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
return;
|
||||
}
|
||||
notifyFeaturesAndScheduleNotification(currentLicensesMetaData);
|
||||
logLicenseMetaDataStats("Setting last observed metaData", currentLicensesMetaData);
|
||||
lastObservedLicensesState.set(currentLicensesMetaData);
|
||||
}
|
||||
|
||||
|
@ -493,7 +498,6 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logLicenseMetaDataStats("Setting last observed metaData", currentLicensesMetaData);
|
||||
if (nextScheduleFrequency == -1l) {
|
||||
logger.debug("no need to schedule next notification");
|
||||
} else {
|
||||
|
@ -506,10 +510,22 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
}
|
||||
|
||||
private void logLicenseMetaDataStats(String prefix, LicensesMetaData licensesMetaData) {
|
||||
if (licensesMetaData != null) {
|
||||
logger.debug(prefix + " LicensesMetaData: signedLicenses: " + licensesMetaData.getSignatures().size() + " trialLicenses: " + licensesMetaData.getEncodedTrialLicenses().size());
|
||||
} else {
|
||||
logger.debug(prefix + " LicensesMetaData: signedLicenses: 0 trialLicenses: 0");
|
||||
if (logger.isDebugEnabled()) {
|
||||
if (licensesMetaData != null) {
|
||||
StringBuilder signedFeatures = new StringBuilder();
|
||||
for (ESLicense license : licenseManager.fromSignatures(licensesMetaData.getSignatures())) {
|
||||
signedFeatures.append(license.feature());
|
||||
signedFeatures.append(", ");
|
||||
}
|
||||
StringBuilder trialFeatures = new StringBuilder();
|
||||
for (ESLicense license : TrialLicenseUtils.fromEncodedTrialLicenses(licensesMetaData.getEncodedTrialLicenses())) {
|
||||
trialFeatures.append(license.feature());
|
||||
trialFeatures.append(", ");
|
||||
}
|
||||
logger.debug(prefix + " LicensesMetaData: signedLicenses: [" + signedFeatures.toString() + "] trialLicenses: [" + trialFeatures.toString() + "]");
|
||||
} else {
|
||||
logger.debug(prefix + " LicensesMetaData: signedLicenses: [] trialLicenses: []");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,7 +553,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
*
|
||||
* @param listenerHolder of the feature to register
|
||||
* @return true if registration has been completed, false otherwise (if masterNode is not available & trail license spec is provided)
|
||||
* or if there is a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
* or if there is a global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK}
|
||||
*/
|
||||
private boolean registerListener(final ListenerHolder listenerHolder) {
|
||||
logger.debug("Registering listener for " + listenerHolder.feature);
|
||||
|
@ -644,7 +660,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
/**
|
||||
* Job for notifying on expired license(s) to registered feature(s)
|
||||
* In case of a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK},
|
||||
* In case of a global block on {@link GatewayService#STATE_NOT_RECOVERED_BLOCK},
|
||||
* the notification is not run, instead the feature(s) would be notified on the next
|
||||
* {@link #clusterChanged(org.elasticsearch.cluster.ClusterChangedEvent)} with no global block
|
||||
*/
|
||||
|
@ -717,12 +733,14 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
private void enableFeatureIfNeeded() {
|
||||
if (enabled.compareAndSet(false, true)) {
|
||||
logger.debug("feature: " + feature + " calling onEnabled");
|
||||
listener.onEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
private void disableFeatureIfNeeded() {
|
||||
if (enabled.compareAndSet(true, false)) {
|
||||
logger.debug("feature: " + feature + " calling onDisabled");
|
||||
listener.onDisabled();
|
||||
}
|
||||
}
|
||||
|
@ -733,7 +751,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
}
|
||||
|
||||
/**
|
||||
* Thin wrapper to work with {@link org.elasticsearch.license.plugin.core.LicensesMetaData}
|
||||
* Thin wrapper to work with {@link LicensesMetaData}
|
||||
* Never mutates the wrapped metaData
|
||||
*/
|
||||
private static class LicensesWrapper {
|
||||
|
|
|
@ -11,16 +11,20 @@ import org.elasticsearch.cluster.ProcessedClusterStateUpdateTask;
|
|||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.base.Predicate;
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.core.ESLicense;
|
||||
import org.elasticsearch.license.licensor.ESLicenseSigner;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService;
|
||||
import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginServiceBase;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
|
||||
|
@ -92,6 +96,14 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte
|
|||
return signer.sign(licenseSpec);
|
||||
}
|
||||
|
||||
protected void putLicense(String feature, TimeValue expiryDuration) throws Exception {
|
||||
ESLicense license1 = generateSignedLicense(feature, expiryDuration);
|
||||
final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster()).setLicense(Lists.newArrayList(license1)).get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
}
|
||||
|
||||
|
||||
protected void assertLicenseManagerEnabledFeatureFor(final String feature) throws InterruptedException {
|
||||
assertLicenseManagerStatusFor(feature, true);
|
||||
}
|
||||
|
@ -101,7 +113,7 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte
|
|||
}
|
||||
|
||||
protected void assertLicenseManagerStatusFor(final String feature, final boolean expectedEnabled) throws InterruptedException {
|
||||
assertThat(awaitBusy(new Predicate<Object>() {
|
||||
assertThat("LicenseManager for feature " + feature + " should have enabled status of " + expectedEnabled, awaitBusy(new Predicate<Object>() {
|
||||
@Override
|
||||
public boolean apply(Object o) {
|
||||
for (LicensesManagerService managerService : licensesManagerServices()) {
|
||||
|
@ -133,17 +145,17 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte
|
|||
protected void assertLazyConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
final List<TestPluginServiceBase> consumerPluginServices = consumerLazyPluginServices();
|
||||
assertThat("At least one instance has to be present", consumerPluginServices.size(), greaterThan(0));
|
||||
assertConsumerPluginNotification(consumerPluginServices, expectedEnabled, timeoutInSec);
|
||||
assertConsumerPluginNotification("LazyConsumer should have license status of: " + expectedEnabled, consumerPluginServices, expectedEnabled, timeoutInSec);
|
||||
}
|
||||
|
||||
protected void assertEagerConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
final List<TestPluginServiceBase> consumerPluginServices = consumerEagerPluginServices();
|
||||
assertThat("At least one instance has to be present", consumerPluginServices.size(), greaterThan(0));
|
||||
assertConsumerPluginNotification(consumerPluginServices, expectedEnabled, timeoutInSec);
|
||||
assertConsumerPluginNotification("EagerConsumer should have license status of: " + expectedEnabled, consumerPluginServices, expectedEnabled, timeoutInSec);
|
||||
}
|
||||
|
||||
private void assertConsumerPluginNotification(final Iterable<TestPluginServiceBase> consumerPluginServices, final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
assertThat(awaitBusy(new Predicate<Object>() {
|
||||
private void assertConsumerPluginNotification(String msg, final Iterable<TestPluginServiceBase> consumerPluginServices, final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
assertThat(msg, awaitBusy(new Predicate<Object>() {
|
||||
@Override
|
||||
public boolean apply(Object o) {
|
||||
for (TestPluginServiceBase pluginService : consumerPluginServices) {
|
||||
|
|
|
@ -6,19 +6,14 @@
|
|||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.common.base.Predicate;
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.license.core.ESLicense;
|
||||
import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin;
|
||||
import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin;
|
||||
import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
|
@ -31,7 +26,7 @@ public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationT
|
|||
|
||||
private final boolean useEagerLicenseRegistrationPlugin = randomBoolean();
|
||||
|
||||
private final int trialLicenseDurationInSeconds = 2;
|
||||
private final int trialLicenseDurationInSeconds = 5;
|
||||
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return ImmutableSettings.settingsBuilder()
|
||||
|
@ -69,10 +64,7 @@ public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationT
|
|||
assertLicenseManagerDisabledFeatureFor(getCurrentFeatureName());
|
||||
|
||||
logger.info(" --> put signed license");
|
||||
ESLicense license = generateSignedLicense(getCurrentFeatureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster()).setLicense(Lists.newArrayList(license)).get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
putLicense(getCurrentFeatureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
|
||||
logger.info(" --> check signed license enabled notification");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
|
@ -111,10 +103,7 @@ public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationT
|
|||
assertConsumerPluginEnabledNotification(1);
|
||||
|
||||
logger.info(" --> put signed license while trial license is in effect");
|
||||
ESLicense license = generateSignedLicense(getCurrentFeatureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2));
|
||||
final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster()).setLicense(Lists.newArrayList(license)).get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
putLicense(getCurrentFeatureName(), TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2));
|
||||
|
||||
logger.info(" --> check signed license enabled notification");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
|
|
|
@ -5,38 +5,30 @@
|
|||
*/
|
||||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.core.ESLicense;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationConsumerPlugin;
|
||||
import org.elasticsearch.license.plugin.consumer.EagerLicenseRegistrationPluginService;
|
||||
import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationConsumerPlugin;
|
||||
import org.elasticsearch.license.plugin.consumer.LazyLicenseRegistrationPluginService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
||||
@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0)
|
||||
public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegrationTests {
|
||||
|
||||
private final int trialLicenseDurationInSeconds = 2;
|
||||
|
||||
private final String FEATURE_NAME_1 = EagerLicenseRegistrationPluginService.FEATURE_NAME;
|
||||
private final String FEATURE_NAME_2 = LazyLicenseRegistrationPluginService.FEATURE_NAME;
|
||||
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return ImmutableSettings.settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
|
||||
.put(LazyLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
|
||||
.put(EagerLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 2)
|
||||
.put(LazyLicenseRegistrationConsumerPlugin.NAME + ".trial_license_duration_in_seconds", 2)
|
||||
.putArray("plugin.types", LicensePlugin.class.getName(), EagerLicenseRegistrationConsumerPlugin.class.getName(), LazyLicenseRegistrationConsumerPlugin.class.getName())
|
||||
.build();
|
||||
}
|
||||
|
@ -59,10 +51,10 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
@Test
|
||||
public void testWithNoTrialLicense() throws Exception {
|
||||
int nNodes = randomIntBetween(2, 10);
|
||||
String[] nodes = startNodesWithConsumerPlugins(nNodes, -1, -1);
|
||||
startNodesWithConsumerPlugins(nNodes, -1, -1);
|
||||
|
||||
assertEagerConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLazyConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertEagerConsumerPluginDisableNotification(1);
|
||||
assertLazyConsumerPluginDisableNotification(1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
}
|
||||
|
@ -71,7 +63,7 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
public void testOneTrialAndNonTrialConsumer() throws Exception {
|
||||
int nNodes = randomIntBetween(2, 10);
|
||||
int consumer2TrialLicenseDuration = 2;
|
||||
String[] nodes = startNodesWithConsumerPlugins(nNodes, -1, consumer2TrialLicenseDuration);
|
||||
startNodesWithConsumerPlugins(nNodes, -1, consumer2TrialLicenseDuration);
|
||||
|
||||
logger.info(" --> trial license generated for " + FEATURE_NAME_2 + " no trial license for " + FEATURE_NAME_1);
|
||||
// managerService should report feature to be enabled on all data nodes
|
||||
|
@ -82,16 +74,11 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
assertLazyConsumerPluginEnableNotification(1);
|
||||
|
||||
logger.info(" --> put signed license for " + FEATURE_NAME_1);
|
||||
ESLicense license1 = generateSignedLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(consumer2TrialLicenseDuration));
|
||||
final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster()).setLicense(Lists.newArrayList(license1)).get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
putLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(consumer2TrialLicenseDuration));
|
||||
|
||||
logger.info(" --> check that both " + FEATURE_NAME_1 + " and " + FEATURE_NAME_2 + " are enabled");
|
||||
assertEagerConsumerPluginEnableNotification(1);
|
||||
assertLazyConsumerPluginEnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2);
|
||||
|
||||
logger.info(" --> check signed license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired signed license)
|
||||
|
@ -105,7 +92,10 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
public void testMultipleConsumerPlugins() throws Exception {
|
||||
|
||||
int nNodes = randomIntBetween(2, 10);
|
||||
String[] nodes = startNodesWithConsumerPlugins(nNodes, trialLicenseDurationInSeconds, trialLicenseDurationInSeconds);
|
||||
int consumer1TrialLicenseExpiry = 2;
|
||||
int consumer2TrialLicenseExpiry = 2;
|
||||
startNodesWithConsumerPlugins(nNodes, consumer1TrialLicenseExpiry, consumer2TrialLicenseExpiry);
|
||||
|
||||
logger.info(" --> trial license generated");
|
||||
// managerService should report feature to be enabled on all data nodes
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1);
|
||||
|
@ -116,14 +106,14 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
|
||||
logger.info(" --> check trial license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired trial license)
|
||||
assertEagerConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLazyConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertEagerConsumerPluginDisableNotification(consumer1TrialLicenseExpiry * 2);
|
||||
assertLazyConsumerPluginDisableNotification(consumer2TrialLicenseExpiry * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
|
||||
logger.info(" --> put signed license");
|
||||
putLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
putLicense(FEATURE_NAME_2, TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
putLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(consumer1TrialLicenseExpiry));
|
||||
putLicense(FEATURE_NAME_2, TimeValue.timeValueSeconds(consumer2TrialLicenseExpiry));
|
||||
|
||||
logger.info(" --> check signed license enabled notification");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
|
@ -134,8 +124,8 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
|
||||
logger.info(" --> check signed license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired signed license)
|
||||
assertEagerConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLazyConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertEagerConsumerPluginDisableNotification(consumer1TrialLicenseExpiry * 2);
|
||||
assertLazyConsumerPluginDisableNotification(consumer2TrialLicenseExpiry * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
}
|
||||
|
@ -143,27 +133,27 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
@Test
|
||||
public void testRandomFeatureLicensesActions() throws Exception {
|
||||
int nNodes = randomIntBetween(2, 10);
|
||||
int trialLicenseDuration1 = rarely() ? -1 : randomIntBetween(1, 2);
|
||||
int trialLicenseDuration2 = rarely() ? -1 : randomIntBetween(1, 2);
|
||||
int trialLicenseDuration1 = rarely() ? -1 : randomIntBetween(2, 3);
|
||||
int trialLicenseDuration2 = rarely() ? -1 : randomIntBetween(2, 3);
|
||||
|
||||
String[] nodes = startNodesWithConsumerPlugins(nNodes, trialLicenseDuration1, trialLicenseDuration2);
|
||||
startNodesWithConsumerPlugins(nNodes, trialLicenseDuration1, trialLicenseDuration2);
|
||||
|
||||
if (trialLicenseDuration1 != -1) {
|
||||
assertEagerConsumerPluginEnableNotification(1);
|
||||
assertEagerConsumerPluginEnableNotification(trialLicenseDuration1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1);
|
||||
} else {
|
||||
assertEagerConsumerPluginDisableNotification(1);
|
||||
assertEagerConsumerPluginDisableNotification(3 * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
putLicense(FEATURE_NAME_1, TimeValue.timeValueMillis(300 * 2));
|
||||
putLicense(FEATURE_NAME_1, TimeValue.timeValueMillis(500 * 2));
|
||||
}
|
||||
|
||||
if (trialLicenseDuration2 != -1) {
|
||||
assertLazyConsumerPluginEnableNotification(1);
|
||||
assertLazyConsumerPluginEnableNotification(trialLicenseDuration2);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2);
|
||||
} else {
|
||||
assertLazyConsumerPluginDisableNotification(1);
|
||||
assertLazyConsumerPluginDisableNotification(3 * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
putLicense(FEATURE_NAME_2, TimeValue.timeValueMillis(300 * 2));
|
||||
putLicense(FEATURE_NAME_2, TimeValue.timeValueMillis(500 * 2));
|
||||
}
|
||||
|
||||
logger.info(" --> check license enabled notification");
|
||||
|
@ -174,25 +164,16 @@ public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegration
|
|||
|
||||
logger.info(" --> check license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired signed license)
|
||||
assertEagerConsumerPluginDisableNotification(2 * 2);
|
||||
assertLazyConsumerPluginDisableNotification(2 * 2);
|
||||
assertEagerConsumerPluginDisableNotification(3 * 2);
|
||||
assertLazyConsumerPluginDisableNotification(3 * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
|
||||
}
|
||||
|
||||
private String[] startNodesWithConsumerPlugins(int nNodes, int consumer1TrialLicenseDuration, int consumer2TrialLicenseDuration) {
|
||||
String[] nodes = new String[nNodes];
|
||||
private void startNodesWithConsumerPlugins(int nNodes, int consumer1TrialLicenseDuration, int consumer2TrialLicenseDuration) {
|
||||
for (int i = 0; i < nNodes; i++) {
|
||||
nodes[i] = internalCluster().startNode(nodeSettingsWithConsumerPlugin(consumer1TrialLicenseDuration, consumer2TrialLicenseDuration));
|
||||
internalCluster().startNode(nodeSettingsWithConsumerPlugin(consumer1TrialLicenseDuration, consumer2TrialLicenseDuration));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
private void putLicense(String feature, TimeValue expiryDuration) throws Exception {
|
||||
ESLicense license1 = generateSignedLicense(feature, expiryDuration);
|
||||
final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster()).setLicense(Lists.newArrayList(license1)).get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,8 +109,9 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
final TimeValue expiryDuration = TimeValue.timeValueSeconds(2);
|
||||
actions.add(registerWithTrialLicense(clientService, clientListener, "feature1", expiryDuration));
|
||||
actions.add(assertExpiryAction("trial", expiryDuration));
|
||||
String feature1 = "feature1";
|
||||
actions.add(registerWithTrialLicense(clientService, clientListener, feature1, expiryDuration));
|
||||
actions.add(assertExpiryAction(feature1, "trial", expiryDuration));
|
||||
assertClientListenerNotificationCount(clientListener, actions);
|
||||
}
|
||||
|
||||
|
@ -126,14 +127,16 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
List<Action> secondClientActions = new ArrayList<>();
|
||||
|
||||
final TimeValue firstExpiryDuration = TimeValue.timeValueSeconds(2);
|
||||
firstClientActions.add(registerWithoutTrialLicense(licensesService, clientListener1, "feature1"));
|
||||
firstClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, "feature1", firstExpiryDuration));
|
||||
firstClientActions.add(assertExpiryAction("signed", firstExpiryDuration));
|
||||
String feature1 = "feature1";
|
||||
firstClientActions.add(registerWithoutTrialLicense(licensesService, clientListener1, feature1));
|
||||
firstClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature1, firstExpiryDuration));
|
||||
firstClientActions.add(assertExpiryAction(feature1, "signed", firstExpiryDuration));
|
||||
|
||||
final TimeValue secondExpiryDuration = TimeValue.timeValueSeconds(1);
|
||||
secondClientActions.add(registerWithoutTrialLicense(licensesService, clientListener2, "feature2"));
|
||||
secondClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, "feature2", secondExpiryDuration));
|
||||
secondClientActions.add(assertExpiryAction("signed", secondExpiryDuration));
|
||||
String feature2 = "feature2";
|
||||
secondClientActions.add(registerWithoutTrialLicense(licensesService, clientListener2, feature2));
|
||||
secondClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature2, secondExpiryDuration));
|
||||
secondClientActions.add(assertExpiryAction(feature2, "signed", secondExpiryDuration));
|
||||
|
||||
if (randomBoolean()) {
|
||||
assertClientListenerNotificationCount(clientListener1, firstClientActions);
|
||||
|
@ -156,13 +159,15 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
List<Action> secondClientActions = new ArrayList<>();
|
||||
|
||||
final TimeValue firstExpiryDuration = TimeValue.timeValueSeconds(2);
|
||||
firstClientActions.add(registerWithoutTrialLicense(licensesService, clientListener1, "feature1"));
|
||||
firstClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, "feature1", firstExpiryDuration));
|
||||
firstClientActions.add(assertExpiryAction("signed", firstExpiryDuration));
|
||||
String feature1 = "feature1";
|
||||
firstClientActions.add(registerWithoutTrialLicense(licensesService, clientListener1, feature1));
|
||||
firstClientActions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature1, firstExpiryDuration));
|
||||
firstClientActions.add(assertExpiryAction(feature1, "signed", firstExpiryDuration));
|
||||
|
||||
final TimeValue secondExpiryDuration = TimeValue.timeValueSeconds(1);
|
||||
secondClientActions.add(registerWithTrialLicense(licensesService, clientListener2, "feature2", secondExpiryDuration));
|
||||
secondClientActions.add(assertExpiryAction("trial", secondExpiryDuration));
|
||||
String feature2 = "feature2";
|
||||
secondClientActions.add(registerWithTrialLicense(licensesService, clientListener2, feature2, secondExpiryDuration));
|
||||
secondClientActions.add(assertExpiryAction(feature2, "trial", secondExpiryDuration));
|
||||
|
||||
if (randomBoolean()) {
|
||||
assertClientListenerNotificationCount(clientListener1, firstClientActions);
|
||||
|
@ -184,12 +189,14 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
List<Action> secondClientActions = new ArrayList<>();
|
||||
|
||||
TimeValue firstExpiryDuration = TimeValue.timeValueSeconds(1);
|
||||
firstClientActions.add(registerWithTrialLicense(licensesService, clientListener1, "feature1", firstExpiryDuration));
|
||||
firstClientActions.add(assertExpiryAction("trial", firstExpiryDuration));
|
||||
String feature1 = "feature1";
|
||||
firstClientActions.add(registerWithTrialLicense(licensesService, clientListener1, feature1, firstExpiryDuration));
|
||||
firstClientActions.add(assertExpiryAction(feature1, "trial", firstExpiryDuration));
|
||||
|
||||
TimeValue secondExpiryDuration = TimeValue.timeValueSeconds(2);
|
||||
secondClientActions.add(registerWithTrialLicense(licensesService, clientListener2, "feature2", secondExpiryDuration));
|
||||
secondClientActions.add(assertExpiryAction("trial", secondExpiryDuration));
|
||||
String feature2 = "feature2";
|
||||
secondClientActions.add(registerWithTrialLicense(licensesService, clientListener2, feature2, secondExpiryDuration));
|
||||
secondClientActions.add(assertExpiryAction(feature2, "trial", secondExpiryDuration));
|
||||
|
||||
if (randomBoolean()) {
|
||||
assertClientListenerNotificationCount(clientListener1, firstClientActions);
|
||||
|
@ -218,8 +225,9 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
TimeValue expiryDuration = TimeValue.timeValueSeconds(2);
|
||||
actions.add(registerWithTrialLicense(clientService, clientListener, "feature1", expiryDuration));
|
||||
actions.add(assertExpiryAction("trial", expiryDuration));
|
||||
String feature = "feature1";
|
||||
actions.add(registerWithTrialLicense(clientService, clientListener, feature, expiryDuration));
|
||||
actions.add(assertExpiryAction(feature, "trial", expiryDuration));
|
||||
|
||||
assertClientListenerNotificationCount(clientListener, actions);
|
||||
}
|
||||
|
@ -231,19 +239,19 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
Map<TestTrackingClientListener, List<Action>> clientListenersWithActions = new HashMap<>();
|
||||
|
||||
TimeValue expiryDuration = TimeValue.timeValueSeconds(0);
|
||||
for (int i = 0; i < randomIntBetween(10, 20); i++) {
|
||||
for (int i = 0; i < randomIntBetween(5, 10); i++) {
|
||||
final TestTrackingClientListener clientListener = new TestTrackingClientListener();
|
||||
String feature = randomRealisticUnicodeOfCodepointLengthBetween(2, 10);
|
||||
expiryDuration = TimeValue.timeValueMillis(randomIntBetween(1, 5) * 100l + expiryDuration.millis());
|
||||
String feature = "feature_" + String.valueOf(i);
|
||||
expiryDuration = TimeValue.timeValueMillis(randomIntBetween(1, 3) * 1000l + expiryDuration.millis());
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
if (randomBoolean()) {
|
||||
actions.add(registerWithTrialLicense(licensesService, clientListener, feature, expiryDuration));
|
||||
actions.add(assertExpiryAction("trial", expiryDuration));
|
||||
actions.add(assertExpiryAction(feature, "trial", expiryDuration));
|
||||
} else {
|
||||
actions.add(registerWithoutTrialLicense(licensesService, clientListener, feature));
|
||||
actions.add(generateAndPutSignedLicenseAction(masterLicensesManagerService, feature, expiryDuration));
|
||||
actions.add(assertExpiryAction("signed", expiryDuration));
|
||||
actions.add(assertExpiryAction(feature, "signed", expiryDuration));
|
||||
}
|
||||
clientListenersWithActions.put(clientListener, actions);
|
||||
}
|
||||
|
@ -274,8 +282,9 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
}
|
||||
});
|
||||
try {
|
||||
assertThat(latch.await(100, TimeUnit.MILLISECONDS), equalTo(true));
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
fail(e.getMessage());
|
||||
}
|
||||
assertThat(success.get(), equalTo(true));
|
||||
}
|
||||
|
@ -320,51 +329,49 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
}, 0, 1, "should trigger onEnable for " + feature + " once [trial license]");
|
||||
}
|
||||
|
||||
private Action assertExpiryAction(String licenseType, TimeValue expiryDuration) {
|
||||
private Action assertExpiryAction(String feature, String licenseType, TimeValue expiryDuration) {
|
||||
return new Action(new Runnable() {
|
||||
@Override
|
||||
public void run() {}
|
||||
}, 1, 0, TimeValue.timeValueMillis(expiryDuration.getMillis() * 2),
|
||||
"should trigger onDisable once [" + licenseType + " license expiry]");
|
||||
"should trigger onDisable for " + feature + " once [" + licenseType + " license expiry]");
|
||||
}
|
||||
|
||||
private void assertClientListenerNotificationCount(final TestTrackingClientListener clientListener, List<Action> actions) throws Exception {
|
||||
assertThat(clientListener.onDisabledCount.get(), equalTo(0));
|
||||
assertThat(clientListener.onEnabledCount.get(), equalTo(0));
|
||||
|
||||
for (final Action action : actions) {
|
||||
final AtomicBoolean actionPerformed = new AtomicBoolean(false);
|
||||
assertThat(action.msg, awaitBusy(new Predicate<Object>() {
|
||||
AtomicInteger previousOnEnabledCount = new AtomicInteger(0);
|
||||
AtomicInteger previousOnDisabledCount = new AtomicInteger(0);
|
||||
final CountDownLatch enableLatch = new CountDownLatch(action.expectedEnabledCount);
|
||||
final CountDownLatch disableLatch = new CountDownLatch(action.expectedDisabledCount);
|
||||
|
||||
@Override
|
||||
public boolean apply(Object o) {
|
||||
if (actionPerformed.compareAndSet(false, true)) {
|
||||
previousOnEnabledCount.set(clientListener.onEnabledCount.get());
|
||||
previousOnDisabledCount.set(clientListener.onDisabledCount.get());
|
||||
action.run();
|
||||
}
|
||||
clientListener.latch(enableLatch, disableLatch);
|
||||
action.run();
|
||||
|
||||
if (action.expectedEnabledCount > 0) {
|
||||
assertThat(action.msg, enableLatch.await(action.timeout.getMillis() * 2, TimeUnit.MILLISECONDS), equalTo(true));
|
||||
} else if (action.expectedDisabledCount > 0) {
|
||||
assertThat(action.msg, disableLatch.await(action.timeout.getMillis() * 2, TimeUnit.MILLISECONDS), equalTo(true));
|
||||
|
||||
}
|
||||
|
||||
return ((clientListener.onEnabledCount.get() - previousOnEnabledCount.get()) == action.expectedEnabledCount
|
||||
&& (clientListener.onDisabledCount.get() - previousOnDisabledCount.get()) == action.expectedDisabledCount);
|
||||
}
|
||||
}, action.timeout.getMillis(), TimeUnit.MILLISECONDS), equalTo(true));
|
||||
}
|
||||
}
|
||||
|
||||
private class TestTrackingClientListener implements LicensesClientService.Listener {
|
||||
AtomicInteger onEnabledCount = new AtomicInteger(0);
|
||||
AtomicInteger onDisabledCount = new AtomicInteger(0);
|
||||
CountDownLatch enableLatch;
|
||||
CountDownLatch disableLatch;
|
||||
|
||||
public synchronized void latch(CountDownLatch enableLatch, CountDownLatch disableLatch) {
|
||||
this.enableLatch = enableLatch;
|
||||
this.disableLatch = disableLatch;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnabled() {
|
||||
onEnabledCount.incrementAndGet();
|
||||
this.enableLatch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisabled() {
|
||||
onDisabledCount.incrementAndGet();
|
||||
this.disableLatch.countDown();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue