LicensesService: make sure feature registration happens only after first cluster changed event
Tests: added multiple plugin integration tests Minor fixes Original commit: elastic/x-pack-elasticsearch@d9a20b4a10
This commit is contained in:
parent
7d41146f38
commit
dc8e3850e4
|
@ -289,7 +289,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
@Override
|
||||
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||
// Change to debug
|
||||
logger.info("Processed Trial License registration");
|
||||
logger.debug("Processed Trial License registration");
|
||||
LicensesMetaData licensesMetaData = newState.metaData().custom(LicensesMetaData.TYPE);
|
||||
logLicenseMetaDataStats("new", licensesMetaData);
|
||||
}
|
||||
|
@ -314,7 +314,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
@Override
|
||||
public void onFailure(String source, @Nullable Throwable t) {
|
||||
logger.info("LicensesService: " + source, t);
|
||||
logger.debug("LicensesService: " + source, t);
|
||||
}
|
||||
|
||||
private boolean checkTrialLicenseGenerationCondition(String feature, LicensesWrapper licensesWrapper) {
|
||||
|
@ -344,7 +344,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
@Override
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
//Change to debug
|
||||
logger.info("Started LicensesService");
|
||||
logger.debug("Started LicensesService");
|
||||
clusterService.add(this);
|
||||
}
|
||||
|
||||
|
@ -372,7 +372,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
@Override
|
||||
protected void doClose() throws ElasticsearchException {
|
||||
logger.info("Closing LicensesService");
|
||||
logger.debug("Closing LicensesService");
|
||||
transportService.removeHandler(REGISTER_TRIAL_LICENSE_ACTION_NAME);
|
||||
}
|
||||
|
||||
|
@ -400,13 +400,13 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
ListenerHolder pendingRegistrationLister;
|
||||
while ((pendingRegistrationLister = pendingListeners.poll()) != null) {
|
||||
boolean masterAvailable = registerListener(pendingRegistrationLister);
|
||||
logger.info("trying to register pending listener for " + pendingRegistrationLister.feature + " masterAvailable: " + masterAvailable);
|
||||
logger.debug("trying to register pending listener for " + pendingRegistrationLister.feature + " masterAvailable: " + masterAvailable);
|
||||
if (!masterAvailable) {
|
||||
// if the master is not available do not, break out of trying pendingListeners
|
||||
pendingListeners.add(pendingRegistrationLister);
|
||||
break;
|
||||
} else {
|
||||
logger.info("successfully registered listener for: " + pendingRegistrationLister.feature);
|
||||
logger.debug("successfully registered listener for: " + pendingRegistrationLister.feature);
|
||||
registeredListeners.add(pendingRegistrationLister);
|
||||
// make sure to notify new registered feature
|
||||
// notifications could have been scheduled for it before it was registered
|
||||
|
@ -418,14 +418,14 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
// notify all interested plugins
|
||||
// Change to debug
|
||||
if (previousClusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) || addedNewRegisteredListener) {
|
||||
logger.info("calling notifyFeaturesAndScheduleNotification from clusterChanged");
|
||||
logger.debug("calling notifyFeaturesAndScheduleNotification from clusterChanged");
|
||||
notifyFeaturesAndScheduleNotification(currentLicensesMetaData);
|
||||
} else {
|
||||
logger.info("calling notifyFeaturesAndScheduleNotificationIfNeeded from clusterChanged");
|
||||
logger.debug("calling notifyFeaturesAndScheduleNotificationIfNeeded from clusterChanged");
|
||||
notifyFeaturesAndScheduleNotificationIfNeeded(currentLicensesMetaData);
|
||||
}
|
||||
} else {
|
||||
logger.info("clusterChanged: no action [has STATE_NOT_RECOVERED_BLOCK]");
|
||||
logger.debug("clusterChanged: no action [has STATE_NOT_RECOVERED_BLOCK]");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -436,7 +436,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
private void notifyFeaturesAndScheduleNotificationIfNeeded(LicensesMetaData currentLicensesMetaData) {
|
||||
final LicensesMetaData lastNotifiedLicensesMetaData = lastObservedLicensesState.get();
|
||||
if (lastNotifiedLicensesMetaData != null && lastNotifiedLicensesMetaData.equals(currentLicensesMetaData)) {
|
||||
logger.info("currentLicensesMetaData has been already notified on");
|
||||
logger.debug("currentLicensesMetaData has been already notified on");
|
||||
return;
|
||||
}
|
||||
notifyFeaturesAndScheduleNotification(currentLicensesMetaData);
|
||||
|
@ -465,34 +465,11 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
*/
|
||||
private long notifyFeatures(LicensesMetaData currentLicensesMetaData) {
|
||||
long nextScheduleFrequency = -1l;
|
||||
StringBuilder sb = new StringBuilder("Registered listeners: [ ");
|
||||
for (ListenerHolder listenerHolder : registeredListeners) {
|
||||
|
||||
sb.append("( ");
|
||||
sb.append("feature:");
|
||||
sb.append(listenerHolder.feature);
|
||||
sb.append(", ");
|
||||
|
||||
long expiryDate;
|
||||
if ((expiryDate = expiryDateForFeature(listenerHolder.feature, currentLicensesMetaData)) != -1l) {
|
||||
sb.append(" license expiry: ");
|
||||
sb.append(expiryDate);
|
||||
sb.append(", ");
|
||||
}
|
||||
long expiryDate = expiryDateForFeature(listenerHolder.feature, currentLicensesMetaData);
|
||||
long expiryDuration = expiryDate - System.currentTimeMillis();
|
||||
|
||||
if (expiryDate == -1l) {
|
||||
sb.append("no trial/signed license found");
|
||||
sb.append(", ");
|
||||
} else {
|
||||
sb.append("license expires in: ");
|
||||
sb.append(TimeValue.timeValueMillis(expiryDuration).toString());
|
||||
sb.append(", ");
|
||||
}
|
||||
|
||||
if (expiryDuration > 0l) {
|
||||
sb.append("calling enableFeatureIfNeeded");
|
||||
|
||||
listenerHolder.enableFeatureIfNeeded();
|
||||
if (nextScheduleFrequency == -1l) {
|
||||
nextScheduleFrequency = expiryDuration;
|
||||
|
@ -500,22 +477,32 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
nextScheduleFrequency = Math.min(expiryDuration, nextScheduleFrequency);
|
||||
}
|
||||
} else {
|
||||
sb.append("calling disableFeatureIfNeeded");
|
||||
listenerHolder.disableFeatureIfNeeded();
|
||||
}
|
||||
sb.append(" )");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
String status;
|
||||
if (expiryDate != -1l) {
|
||||
status = "license expires in : " + TimeValue.timeValueMillis(expiryDate - System.currentTimeMillis());
|
||||
} else {
|
||||
status = "no trial/signed license found";
|
||||
}
|
||||
if (expiryDuration > 0l) {
|
||||
status += " action: enableFeatureIfNeeded";
|
||||
} else {
|
||||
status += " action: disableFeatureIfNeeded";
|
||||
}
|
||||
logger.debug(listenerHolder.toString() + "" + status);
|
||||
}
|
||||
}
|
||||
sb.append("]");
|
||||
// Change to debug
|
||||
logger.info(sb.toString());
|
||||
|
||||
logLicenseMetaDataStats("Setting last observed metaData", currentLicensesMetaData);
|
||||
lastObservedLicensesState.set(currentLicensesMetaData);
|
||||
|
||||
if (nextScheduleFrequency == -1l) {
|
||||
logger.info("no need to schedule next notification");
|
||||
logger.debug("no need to schedule next notification");
|
||||
} else {
|
||||
logger.info("next notification time: " + TimeValue.timeValueMillis(nextScheduleFrequency).toString());
|
||||
logger.debug("next notification time: " + TimeValue.timeValueMillis(nextScheduleFrequency).toString());
|
||||
}
|
||||
|
||||
return nextScheduleFrequency;
|
||||
|
@ -523,9 +510,9 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
}
|
||||
private void logLicenseMetaDataStats(String prefix, LicensesMetaData licensesMetaData) {
|
||||
if (licensesMetaData != null) {
|
||||
logger.info(prefix + " LicensesMetaData: signedLicenses: " + licensesMetaData.getSignatures().size() + " trialLicenses: " + licensesMetaData.getEncodedTrialLicenses().size());
|
||||
logger.debug(prefix + " LicensesMetaData: signedLicenses: " + licensesMetaData.getSignatures().size() + " trialLicenses: " + licensesMetaData.getEncodedTrialLicenses().size());
|
||||
} else {
|
||||
logger.info(prefix + " LicensesMetaData: signedLicenses: 0 trialLicenses: 0");
|
||||
logger.debug(prefix + " LicensesMetaData: signedLicenses: 0 trialLicenses: 0");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -535,13 +522,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
@Override
|
||||
public void register(String feature, TrialLicenseOptions trialLicenseOptions, Listener listener) {
|
||||
final ListenerHolder listenerHolder = new ListenerHolder(feature, trialLicenseOptions, listener);
|
||||
if (registerListener(listenerHolder)) {
|
||||
logger.info("successfully registered listener for: " + listenerHolder.feature);
|
||||
registeredListeners.add(listenerHolder);
|
||||
} else {
|
||||
logger.info("add listener for: " + listenerHolder.feature + " to pending registration queue");
|
||||
pendingListeners.add(listenerHolder);
|
||||
}
|
||||
logger.debug("add listener for: " + listenerHolder.feature + " to pending registration queue");
|
||||
pendingListeners.add(listenerHolder);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -555,10 +537,10 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
* or if there is a global block on {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK})
|
||||
*/
|
||||
private boolean registerListener(final ListenerHolder listenerHolder) {
|
||||
logger.info("Registering listener for " + listenerHolder.feature);
|
||||
logger.debug("Registering listener for " + listenerHolder.feature);
|
||||
ClusterState currentState = clusterService.state();
|
||||
if (currentState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
|
||||
logger.info("Store as pendingRegistration [cluster has NOT_RECOVERED_BLOCK]");
|
||||
logger.debug("Store as pendingRegistration [cluster has NOT_RECOVERED_BLOCK]");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -571,17 +553,17 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
RegisterTrialLicenseRequest request = new RegisterTrialLicenseRequest(listenerHolder.feature,
|
||||
options.duration, options.maxNodes);
|
||||
if (currentState.nodes().localNodeMaster()) {
|
||||
logger.info("Executing trial license request");
|
||||
logger.debug("Executing trial license request");
|
||||
registerTrialLicense(request);
|
||||
} else {
|
||||
DiscoveryNode masterNode = currentState.nodes().masterNode();
|
||||
if (masterNode != null) {
|
||||
logger.info("Sending trial license request to master");
|
||||
logger.debug("Sending trial license request to master");
|
||||
transportService.sendRequest(masterNode,
|
||||
REGISTER_TRIAL_LICENSE_ACTION_NAME, request, EmptyTransportResponseHandler.INSTANCE_SAME);
|
||||
} else {
|
||||
// could not sent register trial license request to master
|
||||
logger.info("Store as pendingRegistration [master not available yet]");
|
||||
logger.debug("Store as pendingRegistration [master not available yet]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -589,13 +571,13 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
// notify feature as clusterChangedEvent may not happen
|
||||
// as no trial or signed license has been found for feature
|
||||
// Change to debug
|
||||
logger.info("Calling notifyFeaturesAndScheduleNotification [no trial license spec provided]");
|
||||
logger.debug("Calling notifyFeaturesAndScheduleNotification [no trial license spec provided]");
|
||||
notifyFeaturesAndScheduleNotification(currentMetaData);
|
||||
}
|
||||
} else {
|
||||
// signed license already found for the new registered
|
||||
// feature, notify feature on registration
|
||||
logger.info("Calling notifyFeaturesAndScheduleNotification [signed/trial license available]");
|
||||
logger.debug("Calling notifyFeaturesAndScheduleNotification [signed/trial license available]");
|
||||
notifyFeaturesAndScheduleNotification(currentMetaData);
|
||||
}
|
||||
return true;
|
||||
|
@ -605,11 +587,11 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
final Map<String, ESLicense> effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData);
|
||||
ESLicense featureLicense;
|
||||
if ((featureLicense = effectiveLicenses.get(feature)) != null) {
|
||||
logger.info("effective license for " + feature + " relative expiry: " +
|
||||
logger.debug("effective license for " + feature + " relative expiry: " +
|
||||
TimeValue.timeValueMillis(effectiveLicenses.get(feature).expiryDate() - System.currentTimeMillis()));
|
||||
return featureLicense.expiryDate();
|
||||
}
|
||||
logger.info("no effective license for " + feature);
|
||||
logger.debug("no effective license for " + feature);
|
||||
return -1l;
|
||||
}
|
||||
|
||||
|
@ -655,9 +637,9 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
try {
|
||||
final TimeValue delay = TimeValue.timeValueMillis(nextScheduleDelay);
|
||||
scheduledNotifications.add(threadPool.schedule(delay, executorName(), new LicensingClientNotificationJob()));
|
||||
logger.info("Scheduling next notification after: " + delay);
|
||||
logger.debug("Scheduling next notification after: " + delay);
|
||||
} catch (EsRejectedExecutionException ex) {
|
||||
logger.info("Couldn't re-schedule licensing client notification job", ex);
|
||||
logger.debug("Couldn't re-schedule licensing client notification job", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,7 +655,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
logger.info("Performing LicensingClientNotificationJob");
|
||||
logger.debug("Performing LicensingClientNotificationJob");
|
||||
|
||||
// next clusterChanged event will deal with the missed notifications
|
||||
ClusterState currentClusterState = clusterService.state();
|
||||
|
@ -681,7 +663,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
LicensesMetaData currentLicensesMetaData = currentClusterState.metaData().custom(LicensesMetaData.TYPE);
|
||||
notifyFeaturesAndScheduleNotification(currentLicensesMetaData);
|
||||
} else {
|
||||
logger.info("skip notification [STATE_NOT_RECOVERED_BLOCK]");
|
||||
logger.debug("skip notification [STATE_NOT_RECOVERED_BLOCK]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -744,6 +726,10 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
|||
listener.onDisabled();
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "(feature: " + feature + ", enabled: " + enabled.get() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,12 +16,15 @@ 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.consumer.TestPluginService1;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginService2;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginServiceBase;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
|
@ -110,18 +113,37 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte
|
|||
}, 2, TimeUnit.SECONDS), equalTo(true));
|
||||
}
|
||||
|
||||
protected void assertConsumerPluginDisableNotification(int timeoutInSec) throws InterruptedException {
|
||||
assertConsumerPluginNotification(false, timeoutInSec);
|
||||
}
|
||||
protected void assertConsumerPluginEnableNotification(int timeoutInSec) throws InterruptedException {
|
||||
assertConsumerPluginNotification(true, timeoutInSec);
|
||||
protected void assertConsumerPlugin1DisableNotification(int timeoutInSec) throws InterruptedException {
|
||||
assertConsumerPlugin1Notification(false, timeoutInSec);
|
||||
}
|
||||
|
||||
protected void assertConsumerPluginNotification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
protected void assertConsumerPlugin1EnableNotification(int timeoutInSec) throws InterruptedException {
|
||||
assertConsumerPlugin1Notification(true, timeoutInSec);
|
||||
}
|
||||
|
||||
protected void assertConsumerPlugin2DisableNotification(int timeoutInSec) throws InterruptedException {
|
||||
assertConsumerPlugin2Notification(false, timeoutInSec);
|
||||
}
|
||||
|
||||
protected void assertConsumerPlugin2EnableNotification(int timeoutInSec) throws InterruptedException {
|
||||
assertConsumerPlugin2Notification(true, timeoutInSec);
|
||||
}
|
||||
|
||||
protected void assertConsumerPlugin2Notification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
final Iterable<TestPluginServiceBase> consumerPluginServices = consumerPlugin2Services();
|
||||
assertConsumerPluginNotification(consumerPluginServices, expectedEnabled, timeoutInSec);
|
||||
}
|
||||
|
||||
protected void assertConsumerPlugin1Notification(final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
final Iterable<TestPluginServiceBase> consumerPluginServices = consumerPlugin1Services();
|
||||
assertConsumerPluginNotification(consumerPluginServices, expectedEnabled, timeoutInSec);
|
||||
}
|
||||
|
||||
private void assertConsumerPluginNotification(final Iterable<TestPluginServiceBase> consumerPluginServices, final boolean expectedEnabled, int timeoutInSec) throws InterruptedException {
|
||||
assertThat(awaitBusy(new Predicate<Object>() {
|
||||
@Override
|
||||
public boolean apply(Object o) {
|
||||
for (TestPluginService pluginService : consumerPluginServices()) {
|
||||
for (TestPluginServiceBase pluginService : consumerPluginServices) {
|
||||
if (expectedEnabled != pluginService.enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -129,11 +151,25 @@ public abstract class AbstractLicensesIntegrationTests extends ElasticsearchInte
|
|||
return true;
|
||||
}
|
||||
}, timeoutInSec, TimeUnit.SECONDS), equalTo(true));
|
||||
|
||||
}
|
||||
|
||||
private Iterable<TestPluginService> consumerPluginServices() {
|
||||
private Iterable<TestPluginServiceBase> consumerPlugin2Services() {
|
||||
final InternalTestCluster clients = internalCluster();
|
||||
return clients.getDataNodeInstances(TestPluginService.class);
|
||||
List<TestPluginServiceBase> consumerPluginServices = new ArrayList<>();
|
||||
for (TestPluginServiceBase service : clients.getDataNodeInstances(TestPluginService2.class)) {
|
||||
consumerPluginServices.add(service);
|
||||
}
|
||||
return consumerPluginServices;
|
||||
}
|
||||
|
||||
private Iterable<TestPluginServiceBase> consumerPlugin1Services() {
|
||||
final InternalTestCluster clients = internalCluster();
|
||||
List<TestPluginServiceBase> consumerPluginServices = new ArrayList<>();
|
||||
for (TestPluginServiceBase service : clients.getDataNodeInstances(TestPluginService1.class)) {
|
||||
consumerPluginServices.add(service);
|
||||
}
|
||||
return consumerPluginServices;
|
||||
}
|
||||
|
||||
private Iterable<LicensesManagerService> licensesManagerServices() {
|
||||
|
|
|
@ -5,22 +5,19 @@
|
|||
*/
|
||||
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.license.core.ESLicense;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.consumer.TestConsumerPlugin1;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginService1;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.elasticsearch.test.InternalTestCluster;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
@ -29,13 +26,14 @@ import static org.hamcrest.CoreMatchers.equalTo;
|
|||
public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationTests {
|
||||
|
||||
private final int trialLicenseDurationInSeconds = 2;
|
||||
|
||||
@Override
|
||||
|
||||
private final String FEATURE_NAME = TestPluginService1.FEATURE_NAME;
|
||||
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return ImmutableSettings.settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("test_consumer_plugin.trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
|
||||
.put("plugin.types", LicensePlugin.class.getName() + "," + TestConsumerPlugin.class.getName())
|
||||
.put(TestConsumerPlugin1.NAME + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
|
||||
.put("plugin.types", LicensePlugin.class.getName() + "," + TestConsumerPlugin1.class.getName())
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -48,85 +46,79 @@ public class LicensesPluginIntegrationTests extends AbstractLicensesIntegrationT
|
|||
public void testTrialLicenseAndSignedLicenseNotification() throws Exception {
|
||||
logger.info(" --> trial license generated");
|
||||
// managerService should report feature to be enabled on all data nodes
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
// consumer plugin service should return enabled on all data nodes
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
logger.info(" --> check trial license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired trial license)
|
||||
assertConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPlugin1DisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME);
|
||||
|
||||
logger.info(" --> put signed license");
|
||||
ESLicense license = generateSignedLicense(TestPluginService.FEATURE_NAME, TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
ESLicense license = generateSignedLicense(FEATURE_NAME, 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));
|
||||
|
||||
logger.info(" --> check signed license enabled notification");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
|
||||
logger.info(" --> check signed license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired signed license)
|
||||
assertConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPlugin1DisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTrialLicenseNotification() throws Exception {
|
||||
logger.info(" --> check onEnabled for trial license");
|
||||
// managerService should report feature to be enabled on all data nodes
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
// consumer plugin service should return enabled on all data nodes
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
logger.info(" --> sleep for rest of trailLicense duration");
|
||||
Thread.sleep(trialLicenseDurationInSeconds * 1000l);
|
||||
|
||||
logger.info(" --> check trial license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired signed license)
|
||||
assertConsumerPluginDisableNotification(trialLicenseDurationInSeconds);
|
||||
assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPlugin1DisableNotification(trialLicenseDurationInSeconds);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOverlappingTrialAndSignedLicenseNotification() throws Exception {
|
||||
logger.info(" --> check onEnabled for trial license");
|
||||
// managerService should report feature to be enabled on all data nodes
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
// consumer plugin service should return enabled on all data nodes
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
logger.info(" --> put signed license while trial license is in effect");
|
||||
ESLicense license = generateSignedLicense(TestPluginService.FEATURE_NAME, TimeValue.timeValueSeconds(trialLicenseDurationInSeconds * 2));
|
||||
ESLicense license = generateSignedLicense(FEATURE_NAME, 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));
|
||||
|
||||
logger.info(" --> check signed license enabled notification");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
|
||||
logger.info(" --> sleep for rest of trailLicense duration");
|
||||
Thread.sleep(trialLicenseDurationInSeconds * 1000l);
|
||||
|
||||
logger.info(" --> check consumer is still enabled [signed license]");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
|
||||
logger.info(" --> check signed license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired signed license)
|
||||
assertConsumerPluginDisableNotification(trialLicenseDurationInSeconds * 2 * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
}
|
||||
|
||||
|
||||
private LicensesManagerService masterLicenseManagerService() {
|
||||
final InternalTestCluster clients = internalCluster();
|
||||
return clients.getInstance(LicensesManagerService.class, clients.getMasterName());
|
||||
assertConsumerPlugin1DisableNotification(trialLicenseDurationInSeconds * 2 * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
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.TestConsumerPlugin1;
|
||||
import org.elasticsearch.license.plugin.consumer.TestConsumerPlugin2;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginService1;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginService2;
|
||||
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 = 10, numClientNodes = 0)
|
||||
public class LicensesPluginsIntegrationTests extends AbstractLicensesIntegrationTests {
|
||||
|
||||
private final int trialLicenseDurationInSeconds = 2;
|
||||
|
||||
private final String FEATURE_NAME_1 = TestPluginService1.FEATURE_NAME;
|
||||
private final String FEATURE_NAME_2 = TestPluginService2.FEATURE_NAME;
|
||||
|
||||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return ImmutableSettings.settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put(TestConsumerPlugin1.NAME + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
|
||||
.put(TestConsumerPlugin2.NAME + ".trial_license_duration_in_seconds", trialLicenseDurationInSeconds)
|
||||
.putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin1.class.getName(), TestConsumerPlugin2.class.getName())
|
||||
.build();
|
||||
}
|
||||
|
||||
@After
|
||||
public void beforeTest() throws Exception {
|
||||
wipeAllLicenses();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleConsumerPlugins() throws Exception {
|
||||
logger.info(" --> trial license generated");
|
||||
// managerService should report feature to be enabled on all data nodes
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME_2);
|
||||
// consumer plugin service should return enabled on all data nodes
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
assertConsumerPlugin2EnableNotification(1);
|
||||
|
||||
logger.info(" --> check trial license expiry notification");
|
||||
// consumer plugin should notify onDisabled on all data nodes (expired trial license)
|
||||
assertConsumerPlugin1DisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertConsumerPlugin2DisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
|
||||
logger.info(" --> put signed license");
|
||||
ESLicense license1 = generateSignedLicense(FEATURE_NAME_1, TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
ESLicense license2 = generateSignedLicense(FEATURE_NAME_2, TimeValue.timeValueSeconds(trialLicenseDurationInSeconds));
|
||||
final PutLicenseResponse putLicenseResponse = new PutLicenseRequestBuilder(client().admin().cluster()).setLicense(Lists.newArrayList(license1, license2)).get();
|
||||
assertThat(putLicenseResponse.isAcknowledged(), equalTo(true));
|
||||
assertThat(putLicenseResponse.status(), equalTo(LicensesStatus.VALID));
|
||||
|
||||
logger.info(" --> check signed license enabled notification");
|
||||
// consumer plugin should notify onEnabled on all data nodes (signed license)
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
assertConsumerPlugin2EnableNotification(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)
|
||||
assertConsumerPlugin1DisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertConsumerPlugin2DisableNotification(trialLicenseDurationInSeconds * 2);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_1);
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME_2);
|
||||
}
|
||||
}
|
|
@ -15,10 +15,11 @@ import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder;
|
|||
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.consumer.TestConsumerPlugin1;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginService1;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.elasticsearch.node.internal.InternalNode;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -29,9 +30,10 @@ import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
|
|||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
|
||||
@ClusterScope(scope = TEST, numDataNodes = 0, numClientNodes = 0)
|
||||
public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrationTests {
|
||||
public class LicensesServiceClusterTest extends AbstractLicensesIntegrationTests {
|
||||
|
||||
@Override
|
||||
private final String FEATURE_NAME = TestPluginService1.FEATURE_NAME;
|
||||
|
||||
protected Settings transportClientSettings() {
|
||||
return super.transportClientSettings();
|
||||
}
|
||||
|
@ -48,8 +50,8 @@ public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrati
|
|||
.put("plugins.load_classpath_plugins", false)
|
||||
.put("node.data", true)
|
||||
.put("format", "json")
|
||||
.put("test_consumer_plugin.trial_license_duration_in_seconds", 5)
|
||||
.putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin.class.getName())
|
||||
.put(TestConsumerPlugin1.NAME + ".trial_license_duration_in_seconds", 5)
|
||||
.putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin1.class.getName())
|
||||
.put(InternalNode.HTTP_ENABLED, true);
|
||||
}
|
||||
|
||||
|
@ -60,50 +62,58 @@ public class LicensesServiceClusterRestartTest extends AbstractLicensesIntegrati
|
|||
|
||||
@Test
|
||||
public void testClusterRestart() throws Exception {
|
||||
logger.info("--> starting 1 node");
|
||||
internalCluster().startNode();
|
||||
|
||||
int numNodes = randomIntBetween(1, 5);
|
||||
logger.info("--> starting " + numNodes + " node(s)");
|
||||
for (int i = 0; i < numNodes; i++) {
|
||||
internalCluster().startNode();
|
||||
}
|
||||
ensureGreen();
|
||||
|
||||
logger.info("--> put signed license");
|
||||
final List<ESLicense> esLicenses = generateAndPutLicense();
|
||||
getAndCheckLicense(esLicenses);
|
||||
logger.info("--> restart all nodes");
|
||||
internalCluster().fullRestart();
|
||||
ensureYellow();
|
||||
|
||||
logger.info("--> get and check signed license");
|
||||
getAndCheckLicense(esLicenses);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClusterNotRecovered() throws Exception {
|
||||
|
||||
logger.info("--> start 1 node (should not recover)");
|
||||
internalCluster().startNode(nodeSettingsBuilder(0).put("gateway.recover_after_nodes", 3));
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
|
||||
internalCluster().startNode(nodeSettingsBuilder(1).put("gateway.recover_after_nodes", 3));
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
logger.info("--> start first node (should not recover)");
|
||||
internalCluster().startNode(nodeSettingsBuilder(0).put("gateway.recover_after_master_nodes", 2).put("node.master", true));
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
internalCluster().startNode(nodeSettingsBuilder(2).put("gateway.recover_after_nodes", 3));
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
logger.info("--> start second node (should recover)");
|
||||
internalCluster().startNode(nodeSettingsBuilder(1).put("gateway.recover_after_master_nodes", 2).put("node.master", true));
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
internalCluster().stopRandomNonMasterNode();
|
||||
// sleep for the entire trial license duration
|
||||
assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPluginEnableNotification(1);
|
||||
//internalCluster().startNode(nodeSettingsBuilder(2).put("gateway.expected_master_nodes", 3));
|
||||
//assertLicenseManagerEnabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
//assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
logger.info("--> kill master node");
|
||||
internalCluster().stopCurrentMasterNode();
|
||||
assertLicenseManagerEnabledFeatureFor(FEATURE_NAME);
|
||||
assertConsumerPlugin1EnableNotification(1);
|
||||
|
||||
Thread.sleep(5 * 1050l);
|
||||
internalCluster().startNode(nodeSettingsBuilder(3).put("gateway.recover_after_nodes", 3));
|
||||
assertLicenseManagerDisabledFeatureFor(TestPluginService.FEATURE_NAME);
|
||||
assertConsumerPluginDisableNotification(1);
|
||||
internalCluster().startNode(nodeSettingsBuilder(3).put("gateway.recover_after_master_nodes", 2).put("node.master", true));
|
||||
assertLicenseManagerDisabledFeatureFor(FEATURE_NAME);
|
||||
assertConsumerPlugin1DisableNotification(1);
|
||||
|
||||
}
|
||||
|
||||
private List<ESLicense> generateAndPutLicense() throws Exception {
|
||||
ClusterAdminClient cluster = internalCluster().client().admin().cluster();
|
||||
ESLicense license = generateSignedLicense("shield", TimeValue.timeValueMinutes(1));
|
||||
ESLicense license = generateSignedLicense(FEATURE_NAME, TimeValue.timeValueMinutes(1));
|
||||
PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster);
|
||||
final List<ESLicense> putLicenses = Arrays.asList(license);
|
||||
putLicenseRequestBuilder.setLicense(putLicenses);
|
|
@ -8,6 +8,8 @@ package org.elasticsearch.license.plugin;
|
|||
import org.elasticsearch.common.base.Predicate;
|
||||
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.consumer.TestConsumerPlugin1;
|
||||
import org.elasticsearch.license.plugin.consumer.TestPluginService1;
|
||||
import org.elasticsearch.node.internal.InternalNode;
|
||||
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||
import org.elasticsearch.test.junit.annotations.TestLogging;
|
||||
|
@ -27,8 +29,8 @@ public class LicensesServiceNodeTests extends AbstractLicensesIntegrationTests {
|
|||
protected Settings nodeSettings(int nodeOrdinal) {
|
||||
return ImmutableSettings.settingsBuilder()
|
||||
.put(super.nodeSettings(nodeOrdinal))
|
||||
.put("test_consumer_plugin.trial_license_duration_in_seconds", 10)
|
||||
.putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin.class.getName())
|
||||
.put(TestConsumerPlugin1.NAME + ".trial_license_duration_in_seconds", 5)
|
||||
.putArray("plugin.types", LicensePlugin.class.getName(), TestConsumerPlugin1.class.getName())
|
||||
.put(InternalNode.HTTP_ENABLED, true)
|
||||
.build();
|
||||
}
|
||||
|
@ -36,11 +38,11 @@ public class LicensesServiceNodeTests extends AbstractLicensesIntegrationTests {
|
|||
@Test
|
||||
@TestLogging("_root:DEBUG")
|
||||
public void testPluginStatus() throws Exception {
|
||||
final Iterable<TestPluginService> testPluginServices = internalCluster().getDataNodeInstances(TestPluginService.class);
|
||||
final Iterable<TestPluginService1> testPluginServices = internalCluster().getDataNodeInstances(TestPluginService1.class);
|
||||
assertThat(awaitBusy(new Predicate<Object>() {
|
||||
@Override
|
||||
public boolean apply(Object o) {
|
||||
for (TestPluginService pluginService : testPluginServices) {
|
||||
for (TestPluginService1 pluginService : testPluginServices) {
|
||||
if (!pluginService.enabled()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||
import org.elasticsearch.cluster.ClusterService;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
|
@ -232,7 +233,7 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
for (int i = 0; i < randomIntBetween(3, 10); i++) {
|
||||
final TestTrackingClientListener clientListener = new TestTrackingClientListener();
|
||||
String feature = randomRealisticUnicodeOfCodepointLengthBetween(2, 10);
|
||||
expiryDuration = TimeValue.timeValueMillis(randomIntBetween(1, 5) * 1000l + expiryDuration.millis());
|
||||
expiryDuration = TimeValue.timeValueMillis(randomIntBetween(1, 5) * 100l + expiryDuration.millis());
|
||||
List<Action> actions = new ArrayList<>();
|
||||
|
||||
if (randomBoolean()) {
|
||||
|
@ -309,6 +310,11 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
|||
public void run() {
|
||||
clientService.register(feature, new LicensesService.TrialLicenseOptions(expiryDuration, 10),
|
||||
clientListener);
|
||||
|
||||
// invoke clusterChanged event to flush out pendingRegistration
|
||||
LicensesService licensesService = (LicensesService) clientService;
|
||||
ClusterChangedEvent event = new ClusterChangedEvent("", clusterService().state(), clusterService().state());
|
||||
licensesService.clusterChanged(event);
|
||||
}
|
||||
}, 0, 1, "should trigger onEnable once [trial license]");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.consumer;
|
||||
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
public class TestConsumerPlugin1 extends TestConsumerPluginBase {
|
||||
|
||||
public final static String NAME = "test_consumer_plugin_1";
|
||||
|
||||
@Inject
|
||||
public TestConsumerPlugin1(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends LifecycleComponent> service() {
|
||||
return TestPluginService1.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String pluginName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.consumer;
|
||||
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
||||
public class TestConsumerPlugin2 extends TestConsumerPluginBase {
|
||||
|
||||
public static String NAME = "test_consumer_plugin_2";
|
||||
|
||||
@Inject
|
||||
public TestConsumerPlugin2(Settings settings) {
|
||||
super(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends LifecycleComponent> service() {
|
||||
return TestPluginService2.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String pluginName() {
|
||||
return NAME;
|
||||
}
|
||||
}
|
|
@ -3,24 +3,22 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin;
|
||||
package org.elasticsearch.license.plugin.consumer;
|
||||
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.AbstractPlugin;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class TestConsumerPlugin extends AbstractPlugin {
|
||||
public abstract class TestConsumerPluginBase extends AbstractPlugin {
|
||||
|
||||
private final boolean isEnabled;
|
||||
|
||||
@Inject
|
||||
public TestConsumerPlugin(Settings settings) {
|
||||
public TestConsumerPluginBase(Settings settings) {
|
||||
if (DiscoveryNode.clientNode(settings)) {
|
||||
// Enable plugin only on node clients
|
||||
this.isEnabled = "node".equals(settings.get(Client.CLIENT_TYPE_SETTING));
|
||||
|
@ -31,7 +29,7 @@ public class TestConsumerPlugin extends AbstractPlugin {
|
|||
|
||||
@Override
|
||||
public String name() {
|
||||
return "test_plugin";
|
||||
return pluginName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -44,8 +42,12 @@ public class TestConsumerPlugin extends AbstractPlugin {
|
|||
public Collection<Class<? extends LifecycleComponent>> services() {
|
||||
Collection<Class<? extends LifecycleComponent>> services = Lists.newArrayList();
|
||||
if (isEnabled) {
|
||||
services.add(TestPluginService.class);
|
||||
services.add(service());
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
protected abstract Class<? extends LifecycleComponent> service();
|
||||
|
||||
protected abstract String pluginName();
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.consumer;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Singleton;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesClientService;
|
||||
|
||||
@Singleton
|
||||
public class TestPluginService1 extends TestPluginServiceBase {
|
||||
|
||||
public static String FEATURE_NAME = "feature1";
|
||||
|
||||
@Inject
|
||||
public TestPluginService1(Settings settings, LicensesClientService licensesClientService) {
|
||||
super(settings, licensesClientService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String featureName() {
|
||||
return FEATURE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String settingPrefix() {
|
||||
return TestConsumerPlugin1.NAME;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin.consumer;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Singleton;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesClientService;
|
||||
|
||||
@Singleton
|
||||
public class TestPluginService2 extends TestPluginServiceBase {
|
||||
|
||||
|
||||
public static String FEATURE_NAME = "feature2";
|
||||
|
||||
@Inject
|
||||
public TestPluginService2(Settings settings, LicensesClientService licensesClientService) {
|
||||
super(settings, licensesClientService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String featureName() {
|
||||
return FEATURE_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String settingPrefix() {
|
||||
return TestConsumerPlugin2.NAME;
|
||||
}
|
||||
}
|
|
@ -3,12 +3,10 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin;
|
||||
package org.elasticsearch.license.plugin.consumer;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Singleton;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.license.plugin.core.LicensesClientService;
|
||||
|
@ -16,27 +14,20 @@ import org.elasticsearch.license.plugin.core.LicensesService;
|
|||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@Singleton
|
||||
public class TestPluginService extends AbstractLifecycleComponent<TestPluginService> {
|
||||
public abstract class TestPluginServiceBase extends AbstractLifecycleComponent<TestPluginServiceBase> {
|
||||
|
||||
private LicensesClientService licensesClientService;
|
||||
|
||||
// should be the same string used by the license Manger to generate
|
||||
// signed license
|
||||
static final String FEATURE_NAME = "shield";
|
||||
|
||||
// specify the trial license spec for the feature
|
||||
// example: 30 day trial on 1000 nodes
|
||||
final LicensesService.TrialLicenseOptions trialLicenseOptions;
|
||||
|
||||
private AtomicBoolean enabled = new AtomicBoolean(false);
|
||||
|
||||
@Inject
|
||||
public TestPluginService(Settings settings, LicensesClientService licensesClientService) {
|
||||
public TestPluginServiceBase(Settings settings, LicensesClientService licensesClientService) {
|
||||
super(settings);
|
||||
this.licensesClientService = licensesClientService;
|
||||
int durationInSec = settings.getAsInt("test_consumer_plugin.trial_license_duration_in_seconds", -1);
|
||||
logger.info("Trial license Duration in seconds: " + durationInSec);
|
||||
int durationInSec = settings.getAsInt(settingPrefix() + ".trial_license_duration_in_seconds", -1);
|
||||
if (durationInSec == -1) {
|
||||
this.trialLicenseOptions = null;
|
||||
} else {
|
||||
|
@ -44,13 +35,19 @@ public class TestPluginService extends AbstractLifecycleComponent<TestPluginServ
|
|||
}
|
||||
}
|
||||
|
||||
// should be the same string used by the license Manger to generate
|
||||
// signed license
|
||||
public abstract String featureName();
|
||||
|
||||
public abstract String settingPrefix();
|
||||
|
||||
// check if feature is enabled
|
||||
public boolean enabled() {
|
||||
return enabled.get();
|
||||
}
|
||||
|
||||
protected void doStart() throws ElasticsearchException {
|
||||
licensesClientService.register(FEATURE_NAME,
|
||||
licensesClientService.register(featureName(),
|
||||
trialLicenseOptions,
|
||||
new LicensingClientListener());
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
es.logger.level=DEBUG
|
||||
log4j.rootLogger=${es.logger.level}, out
|
||||
|
||||
log4j.logger.org.apache.http=INFO, out
|
||||
log4j.additivity.org.apache.http=false
|
||||
|
||||
log4j.appender.out=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.out.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.out.layout.conversionPattern=[%d{ISO8601}][%-5p][%-25c] %m%n
|
||||
|
||||
log4j.logger.shield.audit.logfile=TRACE, access_log
|
||||
|
||||
log4j.appender.access_log=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.access_log.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.access_log.layout.conversionPattern=%m%n
|
Loading…
Reference in New Issue