diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java index e6f202371f5..d1fb7b61e78 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/collector/cluster/ClusterInfoCollector.java @@ -60,7 +60,8 @@ public class ClusterInfoCollector extends AbstractCollector results = new ArrayList<>(1); // Retrieves all licenses - List licenses = licenseService.licenses(); + // TODO: we should only work with one license + List licenses = Collections.singletonList(licenseService.license()); // Retrieves additional cluster stats ClusterStatsResponse clusterStats = client.admin().cluster().prepareClusterStats().get(marvelSettings.clusterStatsTimeout()); diff --git a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java index 4a7337ab3cd..0985a898716 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoRenderer.java @@ -37,7 +37,6 @@ public class ClusterInfoRenderer extends AbstractRenderer builder.field(Fields.UID, license.uid()); builder.field(Fields.TYPE, license.type()); builder.dateValueField(Fields.ISSUE_DATE_IN_MILLIS, Fields.ISSUE_DATE, license.issueDate()); - builder.field(Fields.FEATURE, license.feature()); builder.dateValueField(Fields.EXPIRY_DATE_IN_MILLIS, Fields.EXPIRY_DATE, license.expiryDate()); builder.field(Fields.MAX_NODES, license.maxNodes()); builder.field(Fields.ISSUED_TO, license.issuedTo()); @@ -77,7 +76,6 @@ public class ClusterInfoRenderer extends AbstractRenderer static final XContentBuilderString STATUS = new XContentBuilderString("status"); static final XContentBuilderString UID = new XContentBuilderString("uid"); static final XContentBuilderString TYPE = new XContentBuilderString("type"); - static final XContentBuilderString FEATURE = new XContentBuilderString("feature"); static final XContentBuilderString ISSUE_DATE_IN_MILLIS = new XContentBuilderString("issue_date_in_millis"); static final XContentBuilderString ISSUE_DATE = new XContentBuilderString("issue_date"); static final XContentBuilderString EXPIRY_DATE_IN_MILLIS = new XContentBuilderString("expiry_date_in_millis"); diff --git a/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseService.java b/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseService.java index 638fd923110..2d8036bd4e6 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseService.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/license/LicenseService.java @@ -6,110 +6,45 @@ package org.elasticsearch.marvel.license; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.logging.support.LoggerMessageFormat; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.license.plugin.core.LicensesManagerService; -import org.elasticsearch.license.plugin.core.LicensesService; import org.elasticsearch.marvel.MarvelPlugin; import org.elasticsearch.marvel.agent.settings.MarvelSettings; import org.elasticsearch.marvel.mode.Mode; -import java.util.*; -public class LicenseService extends AbstractLifecycleComponent { +public class LicenseService extends AbstractLifecycleComponent implements Licensee { public static final String FEATURE_NAME = MarvelPlugin.NAME; - private static final LicensesService.TrialLicenseOptions TRIAL_LICENSE_OPTIONS = - new LicensesService.TrialLicenseOptions(TimeValue.timeValueHours(30 * 24), 1000); - - private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT); - - static final TimeValue GRACE_PERIOD = days(7); - private final LicensesManagerService managerService; - private final LicensesClientService clientService; + private final LicenseeRegistry clientService; private final MarvelSettings marvelSettings; - private final Collection expirationLoggers; - private final LicensesClientService.AcknowledgementCallback acknowledgementCallback; private volatile Mode mode; - private volatile boolean enabled; + private volatile LicenseState state; private volatile long expiryDate; @Inject - public LicenseService(Settings settings, LicensesClientService clientService, LicensesManagerService managerService, MarvelSettings marvelSettings) { + public LicenseService(Settings settings, LicenseeRegistry clientService, LicensesManagerService managerService, MarvelSettings marvelSettings) { super(settings); this.managerService = managerService; this.clientService = clientService; this.marvelSettings = marvelSettings; this.mode = Mode.LITE; - this.expirationLoggers = Arrays.asList( - new LicensesService.ExpirationCallback.Pre(days(7), days(30), days(1)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# Marvel license will expire on [{}].\n" + - "# Have a new license? please update it. Otherwise, please reach out to your support contact.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - }, - new LicensesService.ExpirationCallback.Pre(days(0), days(7), minutes(10)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# Marvel license will expire on [{}].\n" + - "# Have a new license? please update it. Otherwise, please reach out to your support contact.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - }, - new LicensesService.ExpirationCallback.Post(days(0), GRACE_PERIOD, minutes(10)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - long endOfGracePeriod = license.expiryDate() + GRACE_PERIOD.getMillis(); - logger.error("\n" + - "#\n" + - "# MARVEL LICENSE HAS EXPIRED ON [{}].\n" + - "# MARVEL WILL STOP COLLECTING DATA ON [{}].\n" + - "# HAVE A NEW LICENSE? PLEASE UPDATE IT. OTHERWISE, PLEASE REACH OUT TO YOUR SUPPORT CONTACT.\n" + - "#", DATE_FORMATTER.printer().print(endOfGracePeriod), DATE_FORMATTER.printer().print(license.expiryDate())); - } - } - ); - this.acknowledgementCallback = new LicensesClientService.AcknowledgementCallback() { - @Override - public List acknowledge(License currentLicense, License newLicense) { - switch (newLicense.type()) { - - case "trial": - case "gold": - case "platinum": - return Collections.emptyList(); - - default: // "basic" - we also fall back to basic for an unknown type - return Collections.singletonList(LoggerMessageFormat.format( - "Marvel: Multi-cluster support is disabled for clusters with [{}] licenses.\n" + - "If you are running multiple customers, users won't be able to access this\n" + - "all the clusters with [{}] licenses from a single Marvel instance. To access them\n" + - "a dedicated and separated marvel instance will be required for each cluster", - newLicense.type(), newLicense.type())); - } - } - }; } @Override protected void doStart() throws ElasticsearchException { - clientService.register(FEATURE_NAME, TRIAL_LICENSE_OPTIONS, expirationLoggers, acknowledgementCallback, new InternalListener(this)); + clientService.register(this); } @Override @@ -120,14 +55,6 @@ public class LicenseService extends AbstractLifecycleComponent { protected void doClose() throws ElasticsearchException { } - static TimeValue days(int days) { - return TimeValue.timeValueHours(days * 24); - } - - static TimeValue minutes(int minutes) { - return TimeValue.timeValueMinutes(minutes); - } - /** * @return the current marvel's operating mode */ @@ -138,18 +65,20 @@ public class LicenseService extends AbstractLifecycleComponent { /** * @return all registered licenses */ - public List licenses() { - return managerService.getLicenses(); + public License license() { + return managerService.getLicense(); } /** * @return true if the marvel license is enabled */ public boolean enabled() { - return enabled; + return state == LicenseState.ENABLED || state == LicenseState.GRACE_PERIOD; } /** + * TODO: remove licensing grace period, just check for state == LicensesClientService.LicenseState.GRACE_PERIOD instead + * * @return true if marvel is running within the "grace period", ie when the license * is expired but a given extra delay is not yet elapsed */ @@ -164,30 +93,57 @@ public class LicenseService extends AbstractLifecycleComponent { return expiryDate; } - class InternalListener implements LicensesClientService.Listener { + @Override + public String id() { + return FEATURE_NAME; + } - private final LicenseService service; + @Override + public String[] expirationMessages() { + // TODO add messages to be logged around license expiry + return Strings.EMPTY_ARRAY; + } - public InternalListener(LicenseService service) { - this.service = service; + @Override + public String[] acknowledgmentMessages(License currentLicense, License newLicense) { + switch (newLicense.operationMode()) { + case BASIC: + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case TRIAL: + case GOLD: + case PLATINUM: + return new String[] { + LoggerMessageFormat.format( + "Multi-cluster support is disabled for clusters with [{}] licenses.\n" + + "If you are running multiple customers, users won't be able to access this\n" + + "all the clusters with [{}] licenses from a single Marvel instance. To access them\n" + + "a dedicated and separated marvel instance will be required for each cluster", + newLicense.type(), newLicense.type()) + }; + } + } } + return Strings.EMPTY_ARRAY; + } - @Override - public void onEnabled(License license) { - try { - service.enabled = true; - service.expiryDate = license.expiryDate(); - service.mode = Mode.fromName(license.type()); - } catch (IllegalArgumentException e) { - service.mode = Mode.LITE; + @Override + public void onChange(License license, LicenseState state) { + synchronized (this) { + this.state = state; + if (license != null) { + try { + mode = Mode.fromName(license.type()); + } catch (IllegalArgumentException e) { + mode = Mode.LITE; + } + expiryDate = license.expiryDate(); + } else { + mode = Mode.LITE; + } + if (state == LicenseState.DISABLED) { + mode = Mode.LITE; } - } - - @Override - public void onDisabled(License license) { - service.enabled = false; - service.expiryDate = license.expiryDate(); - service.mode = Mode.LITE; } } } diff --git a/marvel/src/main/java/org/elasticsearch/marvel/mode/Mode.java b/marvel/src/main/java/org/elasticsearch/marvel/mode/Mode.java index 9947aa0008a..4b553363567 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/mode/Mode.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/mode/Mode.java @@ -16,6 +16,8 @@ public enum Mode { /** * Marvel runs in downgraded mode + * + * TODO: do we really need mode? */ TRIAL(0), @@ -55,9 +57,13 @@ public enum Mode { public static Mode fromName(String name) { switch (name.toLowerCase(Locale.ROOT)) { - case "trial": return TRIAL; - case "lite": return LITE; - case "standard" : return STANDARD; + case "trial": + return LITE; + case "basic": + case "gold" : + case "silver": + case "platinum": + return STANDARD; default: throw new ElasticsearchException("unknown marvel mode name [" + name + "]"); } diff --git a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java b/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java index 9a804f6a540..687e9d8475e 100644 --- a/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java +++ b/marvel/src/main/java/org/elasticsearch/marvel/shield/MarvelInternalUserHolder.java @@ -33,7 +33,7 @@ public class MarvelInternalUserHolder { // and full access to .marvel-* and .marvel-data indices .add(Privilege.Index.ALL, MarvelSettings.MARVEL_INDICES_PREFIX + "*") - // note, we don't need _licenses permission as we're taking the licenses + // note, we don't need _license permission as we're taking the licenses // directly form the license service. .build(); diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java b/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java index dc021054911..ba1bd9e864d 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java +++ b/marvel/src/test/java/org/elasticsearch/marvel/agent/collector/AbstractCollectorTestCase.java @@ -17,12 +17,11 @@ import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesManagerService; -import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest; +import org.elasticsearch.license.plugin.action.put.PutLicenseRequest; +import org.elasticsearch.license.plugin.core.*; import org.elasticsearch.marvel.MarvelPlugin; import org.elasticsearch.marvel.agent.settings.MarvelSettings; -import org.elasticsearch.marvel.license.LicenseService; import org.elasticsearch.marvel.shield.MarvelShieldIntegration; import org.elasticsearch.marvel.shield.SecuredClient; import org.elasticsearch.marvel.test.MarvelIntegTestCase; @@ -88,15 +87,13 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { private static License createTestingLicense(long issueDate, long expiryDate) { return License.builder() - .feature(LicenseService.FEATURE_NAME) .expiryDate(expiryDate) .issueDate(issueDate) .issuedTo("AbstractCollectorTestCase") .issuer("test") .maxNodes(Integer.MAX_VALUE) .signature("_signature") - .type("standard") - .subscriptionType("all_is_good") + .type("basic") .uid(String.valueOf(RandomizedTest.systemPropertyAsInt(SysGlobals.CHILDVM_SYSPROP_JVM_ID, 0)) + System.identityHashCode(AbstractCollectorTestCase.class)) .build(); } @@ -107,7 +104,7 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { final License license = createTestingLicense(issueDate, expiryDate); for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) { - service.enable(license); + service.onChange(license, LicenseState.ENABLED); } for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) { service.update(license); @@ -120,7 +117,7 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { final License license = createTestingLicense(issueDate, expiryDate); for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) { - service.disable(license); + service.onChange(license, LicenseState.GRACE_PERIOD); } for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) { service.update(license); @@ -133,7 +130,7 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { final License license = createTestingLicense(issueDate, expiryDate); for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) { - service.disable(license); + service.onChange(license, LicenseState.DISABLED); } for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) { service.update(license); @@ -146,7 +143,7 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { final License license = createTestingLicense(issueDate, expiryDate); for (LicenseServiceForCollectors service : internalCluster().getInstances(LicenseServiceForCollectors.class)) { - service.disable(license); + service.onChange(license, LicenseState.DISABLED); } for (LicensesManagerServiceForCollectors service : internalCluster().getInstances(LicensesManagerServiceForCollectors.class)) { service.update(license); @@ -205,7 +202,7 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { @Override protected void configure() { bind(LicenseServiceForCollectors.class).asEagerSingleton(); - bind(LicensesClientService.class).to(LicenseServiceForCollectors.class); + bind(LicenseeRegistry.class).to(LicenseServiceForCollectors.class); bind(LicensesManagerServiceForCollectors.class).asEagerSingleton(); bind(LicensesManagerService.class).to(LicensesManagerServiceForCollectors.class); } @@ -213,9 +210,9 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { } } - public static class LicenseServiceForCollectors extends AbstractComponent implements LicensesClientService { + public static class LicenseServiceForCollectors extends AbstractComponent implements LicenseeRegistry { - private final List listeners = new ArrayList<>(); + private final List licensees = new ArrayList<>(); @Inject public LicenseServiceForCollectors(Settings settings) { @@ -223,19 +220,13 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { } @Override - public void register(String feature, TrialLicenseOptions trialLicenseOptions, Collection expirationCallbacks, AcknowledgementCallback acknowledgementCallback, Listener listener) { - listeners.add(listener); + public void register(Licensee licensee) { + licensees.add(licensee); } - public void enable(License license) { - for (Listener listener : listeners) { - listener.onEnabled(license); - } - } - - public void disable(License license) { - for (Listener listener : listeners) { - listener.onDisabled(license); + public void onChange(License license, LicenseState state) { + for (Licensee licensee : licensees) { + licensee.onChange(license, state); } } } @@ -245,21 +236,24 @@ public class AbstractCollectorTestCase extends MarvelIntegTestCase { private final Map licenses = Collections.synchronizedMap(new HashMap()); @Override - public void registerLicenses(LicensesService.PutLicenseRequestHolder requestHolder, ActionListener listener) { + public void registerLicense(PutLicenseRequest request, ActionListener listener) { } @Override - public void removeLicenses(LicensesService.DeleteLicenseRequestHolder requestHolder, ActionListener listener) { + public void removeLicense(DeleteLicenseRequest request, ActionListener listener) { } @Override - public Set enabledFeatures() { + public List licenseesWithState(LicenseState state) { return null; } @Override - public List getLicenses() { - return new ArrayList<>(licenses.values()); + public License getLicense() { + // TODO: we only take the first of the licenses that are updated + // FIXME + Iterator iterator = licenses.values().iterator(); + return iterator.hasNext() ? iterator.next() : null; } public void update(License license) { diff --git a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoIT.java b/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoIT.java index fbb44ec612c..8b36b4692b5 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoIT.java +++ b/marvel/src/test/java/org/elasticsearch/marvel/agent/renderer/cluster/ClusterInfoIT.java @@ -93,7 +93,6 @@ public class ClusterInfoIT extends MarvelIntegTestCase { String recalculated = ClusterInfoRenderer.hash(status, uid, type, String.valueOf(expiryDate), clusterUUID); assertThat(hkey, equalTo(recalculated)); - assertThat((String) license.get(ClusterInfoRenderer.Fields.FEATURE.underscore().toString()), not(isEmptyOrNullString())); assertThat((String) license.get(ClusterInfoRenderer.Fields.ISSUER.underscore().toString()), not(isEmptyOrNullString())); assertThat((String) license.get(ClusterInfoRenderer.Fields.ISSUED_TO.underscore().toString()), not(isEmptyOrNullString())); assertThat((Long) license.get(ClusterInfoRenderer.Fields.ISSUE_DATE_IN_MILLIS.underscore().toString()), greaterThan(0L)); diff --git a/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java b/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java index 98f7a5d82a3..7b1d6836e98 100644 --- a/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java +++ b/marvel/src/test/java/org/elasticsearch/marvel/license/LicenseIntegrationTests.java @@ -13,8 +13,9 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.marvel.MarvelPlugin; import org.elasticsearch.marvel.mode.Mode; import org.elasticsearch.marvel.test.MarvelIntegTestCase; @@ -106,26 +107,24 @@ public class LicenseIntegrationTests extends MarvelIntegTestCase { @Override protected void configure() { bind(MockLicenseService.class).asEagerSingleton(); - bind(LicensesClientService.class).to(MockLicenseService.class); + bind(LicenseeRegistry.class).to(MockLicenseService.class); } } - public static class MockLicenseService extends AbstractComponent implements LicensesClientService { + public static class MockLicenseService extends AbstractComponent implements LicenseeRegistry { static final License DUMMY_LICENSE = License.builder() - .feature(LicenseService.FEATURE_NAME) .expiryDate(System.currentTimeMillis()) .issueDate(System.currentTimeMillis()) .issuedTo("LicensingTests") .issuer("test") .maxNodes(Integer.MAX_VALUE) .signature("_signature") - .type("standard") - .subscriptionType("all_is_good") + .type("basic") .uid(String.valueOf(RandomizedTest.systemPropertyAsInt(SysGlobals.CHILDVM_SYSPROP_JVM_ID, 0)) + System.identityHashCode(LicenseIntegrationTests.class)) .build(); - private final List listeners = new ArrayList<>(); + private final List licensees = new ArrayList<>(); @Inject public MockLicenseService(Settings settings) { @@ -134,22 +133,20 @@ public class LicenseIntegrationTests extends MarvelIntegTestCase { } @Override - public void register(String s, LicensesService.TrialLicenseOptions trialLicenseOptions, Collection collection, AcknowledgementCallback acknowledgementCallback, Listener listener) { - listeners.add(listener); + public void register(Licensee licensee) { + licensees.add(licensee); enable(); } public void enable() { - // enabled all listeners (incl. shield) - for (Listener listener : listeners) { - listener.onEnabled(DUMMY_LICENSE); + for (Licensee licensee : licensees) { + licensee.onChange(DUMMY_LICENSE, randomBoolean() ? LicenseState.GRACE_PERIOD : LicenseState.ENABLED); } } public void disable() { - // only disable watcher listener (we need shield to work) - for (Listener listener : listeners) { - listener.onDisabled(DUMMY_LICENSE); + for (Licensee licensee : licensees) { + licensee.onChange(DUMMY_LICENSE, LicenseState.DISABLED); } } } diff --git a/shield/docs/public/managing-shield-licenses.asciidoc b/shield/docs/public/managing-shield-licenses.asciidoc index 8dc8ac8e574..6c4d5d51f9d 100644 --- a/shield/docs/public/managing-shield-licenses.asciidoc +++ b/shield/docs/public/managing-shield-licenses.asciidoc @@ -22,7 +22,7 @@ To install or update the license use the following REST API: [source,shell] ----------------------------------------------------------------------- -curl -XPUT -u admin 'http://:/_licenses' -d @license.json +curl -XPUT -u admin 'http://:/_license' -d @license.json ----------------------------------------------------------------------- Where: @@ -42,7 +42,7 @@ You can list all currently installed licenses by executing the following REST AP [source,shell] ----------------------------------------------------- -curl -XGET -u admin:password 'http://:/_licenses' +curl -XGET -u admin:password 'http://:/_license' ----------------------------------------------------- The response of this command will be a JSON listing all available licenses. In the case of Shield, the following diff --git a/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java b/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java index c62e9c85552..69aff42244f 100644 --- a/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java +++ b/shield/src/main/java/org/elasticsearch/shield/action/ShieldActionFilter.java @@ -16,6 +16,7 @@ import org.elasticsearch.action.support.ActionFilterChain; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.license.plugin.core.LicenseUtils; import org.elasticsearch.shield.User; import org.elasticsearch.shield.action.interceptor.RequestInterceptor; @@ -62,13 +63,8 @@ public class ShieldActionFilter extends AbstractComponent implements ActionFilte this.actionMapper = actionMapper; licenseEventsNotifier.register(new LicenseEventsNotifier.Listener() { @Override - public void enabled() { - licenseEnabled = true; - } - - @Override - public void disabled() { - licenseEnabled = false; + public void notify(LicenseState state) { + licenseEnabled = state != LicenseState.DISABLED; } }); this.requestInterceptors = requestInterceptors; diff --git a/shield/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java b/shield/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java index 5de13445386..1ea9f42b10a 100644 --- a/shield/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java +++ b/shield/src/main/java/org/elasticsearch/shield/license/LicenseEventsNotifier.java @@ -5,6 +5,8 @@ */ package org.elasticsearch.shield.license; +import org.elasticsearch.license.plugin.core.LicenseState; + import java.util.HashSet; import java.util.Set; @@ -26,22 +28,14 @@ public class LicenseEventsNotifier { listeners.add(listener); } - protected void notifyEnabled() { + protected void notify(LicenseState state) { for (Listener listener : listeners) { - listener.enabled(); - } - } - - protected void notifyDisabled() { - for (Listener listener : listeners) { - listener.disabled(); + listener.notify(state); } } public static interface Listener { - void enabled(); - - void disabled(); + void notify(LicenseState state); } } diff --git a/shield/src/main/java/org/elasticsearch/shield/license/LicenseService.java b/shield/src/main/java/org/elasticsearch/shield/license/LicenseService.java index b7506278440..95ae692bfda 100644 --- a/shield/src/main/java/org/elasticsearch/shield/license/LicenseService.java +++ b/shield/src/main/java/org/elasticsearch/shield/license/LicenseService.java @@ -6,99 +6,95 @@ package org.elasticsearch.shield.license; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.shield.ShieldPlugin; -import java.util.*; - /** * */ -public class LicenseService extends AbstractLifecycleComponent { +public class LicenseService extends AbstractLifecycleComponent implements Licensee { public static final String FEATURE_NAME = ShieldPlugin.NAME; - private static final LicensesClientService.TrialLicenseOptions TRIAL_LICENSE_OPTIONS = - new LicensesClientService.TrialLicenseOptions(TimeValue.timeValueHours(30 * 24), 1000); - - private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT); - - private final LicensesClientService licensesClientService; + private final LicenseeRegistry licenseeRegistry; private final LicenseEventsNotifier notifier; - private final Collection expirationLoggers; - private final LicensesClientService.AcknowledgementCallback acknowledgementCallback; - private boolean enabled = false; + private volatile LicenseState state = LicenseState.DISABLED; @Inject - public LicenseService(Settings settings, LicensesClientService licensesClientService, LicenseEventsNotifier notifier) { + public LicenseService(Settings settings, LicenseeRegistry licenseeRegistry, LicenseEventsNotifier notifier) { super(settings); - this.licensesClientService = licensesClientService; + this.licenseeRegistry = licenseeRegistry; this.notifier = notifier; - this.expirationLoggers = Arrays.asList( - new LicensesClientService.ExpirationCallback.Pre(days(7), days(30), days(1)) { - @Override - public void on(License license, LicensesClientService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# Shield license will expire on [{}]. Cluster health, cluster stats and indices stats operations are\n" + - "# blocked on Shield license expiration. All data operations (read and write) continue to work. If you\n" + - "# have a new license, please update it. Otherwise, please reach out to your support contact.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - }, - new LicensesClientService.ExpirationCallback.Pre(days(0), days(7), minutes(10)) { - @Override - public void on(License license, LicensesClientService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# Shield license will expire on [{}]. Cluster health, cluster stats and indices stats operations are\n" + - "# blocked on Shield license expiration. All data operations (read and write) continue to work. If you\n" + - "# have a new license, please update it. Otherwise, please reach out to your support contact.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - }, - new LicensesClientService.ExpirationCallback.Post(days(0), null, minutes(10)) { - @Override - public void on(License license, LicensesClientService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# SHIELD LICENSE EXPIRED ON [{}]! CLUSTER HEALTH, CLUSTER STATS AND INDICES STATS OPERATIONS ARE\n" + - "# NOW BLOCKED. ALL DATA OPERATIONS (READ AND WRITE) CONTINUE TO WORK. IF YOU HAVE A NEW LICENSE, PLEASE\n" + - "# UPDATE IT. OTHERWISE, PLEASE REACH OUT TO YOUR SUPPORT CONTACT.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - } - ); - this.acknowledgementCallback = new LicensesClientService.AcknowledgementCallback() { - @Override - public List acknowledge(License currentLicense, License newLicense) { - // TODO: add messages to be acknowledged when installing newLicense from currentLicense - // NOTE: currentLicense can be null, as a license registration can happen before - // a trial license could be generated - return Collections.emptyList(); - } + } + + @Override + public String id() { + return FEATURE_NAME; + } + + @Override + public String[] expirationMessages() { + return new String[] { + "Cluster health, cluster stats and indices stats operations are blocked", + "All data operations (read and write) continue to work" }; } - public synchronized boolean enabled() { - return enabled; + @Override + public String[] acknowledgmentMessages(License currentLicense, License newLicense) { + switch (newLicense.operationMode()) { + case BASIC: + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case TRIAL: + case GOLD: + case PLATINUM: + return new String[] { "The following Shield functionality will be disabled: authentication, authorization, ip filtering, auditing, SSL will be disabled on node restart. Please restart your node after applying the license." }; + } + } + break; + case GOLD: + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case TRIAL: + case BASIC: + case PLATINUM: + return new String[] { + "Field and document level access control will be disabled" + }; + } + } + break; + } + return Strings.EMPTY_ARRAY; + } + + @Override + public void onChange(License license, LicenseState state) { + synchronized (this) { + this.state = state; + notifier.notify(state); + } + } + public LicenseState state() { + return state; } @Override protected void doStart() throws ElasticsearchException { if (settings.getGroups("tribe", true).isEmpty()) { - licensesClientService.register(FEATURE_NAME, TRIAL_LICENSE_OPTIONS, expirationLoggers, acknowledgementCallback, new InternalListener()); + licenseeRegistry.register(this); } else { //TODO currently we disable licensing on tribe node. remove this once es core supports merging cluster - new InternalListener().onEnabled(null); + onChange(null, LicenseState.ENABLED); } } @@ -109,34 +105,4 @@ public class LicenseService extends AbstractLifecycleComponent { @Override protected void doClose() throws ElasticsearchException { } - - static TimeValue days(int days) { - return TimeValue.timeValueHours(days * 24); - } - - static TimeValue minutes(int minutes) { - return TimeValue.timeValueMinutes(minutes); - } - - class InternalListener implements LicensesClientService.Listener { - - @Override - public void onEnabled(License license) { - synchronized (LicenseService.this) { - logger.info("enabling license for [{}]", FEATURE_NAME); - enabled = true; - notifier.notifyEnabled(); - } - } - - @Override - public void onDisabled(License license) { - synchronized (LicenseService.this) { - logger.info("DISABLING LICENSE FOR [{}]", FEATURE_NAME); - enabled = false; - notifier.notifyDisabled(); - } - } - } - } diff --git a/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java b/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java index 1a94e529b6b..86dd59d3137 100644 --- a/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java +++ b/shield/src/main/java/org/elasticsearch/shield/rest/action/RestShieldInfoAction.java @@ -12,6 +12,7 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.internal.Nullable; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.rest.*; import org.elasticsearch.shield.ShieldBuild; import org.elasticsearch.shield.ShieldPlugin; @@ -71,7 +72,7 @@ public class RestShieldInfoAction extends BaseRestHandler { private Status resolveStatus() { if (shieldEnabled) { - if (licenseService.enabled()) { + if (licenseService.state() != LicenseState.DISABLED) { return Status.ENABLED; } return Status.UNLICENSED; diff --git a/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java b/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java index a351116ea38..1be68833056 100644 --- a/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java +++ b/shield/src/test/java/org/elasticsearch/integration/LicensingTests.java @@ -19,7 +19,9 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.shield.license.LicenseService; @@ -169,13 +171,13 @@ public class LicensingTests extends ShieldIntegTestCase { } public static void disableLicensing() { - for (InternalLicensesClientService service : internalCluster().getInstances(InternalLicensesClientService.class)) { + for (InternalLicenseeRegistry service : internalCluster().getInstances(InternalLicenseeRegistry.class)) { service.disable(); } } public static void enableLicensing() { - for (InternalLicensesClientService service : internalCluster().getInstances(InternalLicensesClientService.class)) { + for (InternalLicenseeRegistry service : internalCluster().getInstances(InternalLicenseeRegistry.class)) { service.enable(); } } @@ -203,49 +205,47 @@ public class LicensingTests extends ShieldIntegTestCase { public static class InternalLicenseModule extends AbstractModule { @Override protected void configure() { - bind(InternalLicensesClientService.class).asEagerSingleton(); - bind(LicensesClientService.class).to(InternalLicensesClientService.class); + bind(InternalLicenseeRegistry.class).asEagerSingleton(); + bind(LicenseeRegistry.class).to(InternalLicenseeRegistry.class); } } - public static class InternalLicensesClientService extends AbstractComponent implements LicensesClientService { + public static class InternalLicenseeRegistry extends AbstractComponent implements LicenseeRegistry { - private final List listeners = new ArrayList<>(); + private final List licensees = new ArrayList<>(); static final License DUMMY_LICENSE = License.builder() - .feature(LicenseService.FEATURE_NAME) .expiryDate(System.currentTimeMillis()) .issueDate(System.currentTimeMillis()) .issuedTo("LicensingTests") .issuer("test") .maxNodes(Integer.MAX_VALUE) .signature("_signature") - .type("test_license_for_shield") - .subscriptionType("all_is_good") + .type("basic") .uid(String.valueOf(randomLong()) + System.identityHashCode(LicensingTests.class)) .build(); @Inject - public InternalLicensesClientService(Settings settings) { + public InternalLicenseeRegistry(Settings settings) { super(settings); enable(); } @Override - public void register(String s, LicensesClientService.TrialLicenseOptions trialLicenseOptions, Collection collection, AcknowledgementCallback acknowledgementCallback, Listener listener) { - listeners.add(listener); + public void register(Licensee licensee) { + licensees.add(licensee); enable(); } void enable() { - for (Listener listener : listeners) { - listener.onEnabled(DUMMY_LICENSE); + for (Licensee licensee : licensees) { + licensee.onChange(DUMMY_LICENSE, LicenseState.ENABLED); } } void disable() { - for (Listener listener : listeners) { - listener.onDisabled(DUMMY_LICENSE); + for (Licensee licensee : licensees) { + licensee.onChange(DUMMY_LICENSE, LicenseState.DISABLED); } } } diff --git a/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java b/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java index f5992c5bd8e..99d0d9e7192 100644 --- a/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java +++ b/shield/src/test/java/org/elasticsearch/shield/action/ShieldActionFilterTests.java @@ -11,6 +11,7 @@ import org.elasticsearch.action.ActionRequest; import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.support.ActionFilterChain; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.shield.User; import org.elasticsearch.shield.action.interceptor.RequestInterceptor; import org.elasticsearch.shield.audit.AuditTrail; @@ -112,7 +113,7 @@ public class ShieldActionFilterTests extends ESTestCase { private class MockLicenseEventsNotifier extends LicenseEventsNotifier { @Override public void register(MockLicenseEventsNotifier.Listener listener) { - listener.enabled(); + listener.notify(LicenseState.ENABLED); } } } diff --git a/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseService.java b/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseService.java index 41463a8e865..f19c22b1773 100644 --- a/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseService.java +++ b/watcher/src/main/java/org/elasticsearch/watcher/license/LicenseService.java @@ -6,93 +6,70 @@ package org.elasticsearch.watcher.license; import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.inject.Inject; -import org.elasticsearch.common.joda.FormatDateTimeFormatter; -import org.elasticsearch.common.joda.Joda; import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.watcher.WatcherPlugin; -import java.util.*; - /** * */ -public class LicenseService extends AbstractLifecycleComponent { +public class LicenseService extends AbstractLifecycleComponent implements Licensee { public static final String FEATURE_NAME = WatcherPlugin.NAME; - private static final LicensesClientService.TrialLicenseOptions TRIAL_LICENSE_OPTIONS = - new LicensesClientService.TrialLicenseOptions(TimeValue.timeValueHours(30 * 24), 1000); - - private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT); - - private final LicensesClientService clientService; - private final Collection expirationLoggers; - private final LicensesClientService.AcknowledgementCallback acknowledgementCallback; - - private volatile boolean enabled; + private final LicenseeRegistry clientService; + private volatile LicenseState state; @Inject - public LicenseService(Settings settings, LicensesClientService clientService) { + public LicenseService(Settings settings, LicenseeRegistry clientService) { super(settings); this.clientService = clientService; - this.expirationLoggers = Arrays.asList( - new LicensesService.ExpirationCallback.Pre(days(7), days(30), days(1)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# Watcher license will expire on [{}]. All configured actions on\n" + - "# all registered watches are throttled (not executed) on Watcher license expiration. \n" + - "# Watches will continue be evaluated and watch history will continue being recorded.\n" + - "# Have a new license? please update it. Otherwise, please reach out to your support contact.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - }, - new LicensesService.ExpirationCallback.Pre(days(0), days(7), minutes(10)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# Watcher license will expire on [{}]. All configured actions on\n" + - "# all registered watches are throttled (not executed) on Watcher license expiration. \n" + - "# Watches will continue be evaluated and watch history will continue being recorded.\n" + - "# Have a new license? please update it. Otherwise, please reach out to your support contact.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); - } - }, - new LicensesService.ExpirationCallback.Post(days(0), null, minutes(10)) { - @Override - public void on(License license, LicensesService.ExpirationStatus status) { - logger.error("\n" + - "#\n" + - "# WATCHER LICENSE WAS EXPIRED ON [{}]. ALL CONFIGURED ACTIONS ON\n" + - "# ALL REGISTERED WATCHES ARE THROTTLED (NOT EXECUTED) ON WATCHER LICENSE EXPIRATION. \n" + - "# WATCHES WILL CONTINUE BE EVALUATED AND WATCH HISTORY WILL CONTINUE BEING RECORDED.\n" + - "# HAVE A NEW LICENSE? PLEASE UPDATE IT. OTHERWISE, PLEASE REACH OUT TO YOUR SUPPORT CONTACT.\n" + - "#", DATE_FORMATTER.printer().print(license.expiryDate())); + } + + @Override + public String id() { + return FEATURE_NAME; + } + + @Override + public String[] expirationMessages() { + // TODO add messages to be logged around license expiry + return new String[0]; + } + + @Override + public String[] acknowledgmentMessages(License currentLicense, License newLicense) { + switch (newLicense.operationMode()) { + case BASIC: + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case TRIAL: + case GOLD: + case PLATINUM: + return new String[] { "Watcher will be disabled" }; } } - ); - this.acknowledgementCallback = new LicensesClientService.AcknowledgementCallback() { - @Override - public List acknowledge(License currentLicense, License newLicense) { - // TODO: add messages to be acknowledged when installing newLicense from currentLicense - // NOTE: currentLicense can be null, as a license registration can happen before - // a trial license could be generated - return Collections.emptyList(); - } - }; + break; + } + return Strings.EMPTY_ARRAY; + } + + @Override + public void onChange(License license, LicenseState state) { + synchronized (this) { + this.state = state; + } } @Override protected void doStart() throws ElasticsearchException { - clientService.register(FEATURE_NAME, TRIAL_LICENSE_OPTIONS, expirationLoggers, acknowledgementCallback, new InternalListener(this)); + clientService.register(this); } @Override @@ -104,33 +81,6 @@ public class LicenseService extends AbstractLifecycleComponent { } public boolean enabled() { - return enabled; - } - - static TimeValue days(int days) { - return TimeValue.timeValueHours(days * 24); - } - - static TimeValue minutes(int minutes) { - return TimeValue.timeValueMinutes(minutes); - } - - class InternalListener implements LicensesClientService.Listener { - - private final LicenseService service; - - public InternalListener(LicenseService service) { - this.service = service; - } - - @Override - public void onEnabled(License license) { - service.enabled = true; - } - - @Override - public void onDisabled(License license) { - service.enabled = false; - } + return state != LicenseState.DISABLED; } } diff --git a/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseIntegrationTests.java b/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseIntegrationTests.java index 41d0853440b..cd5cc13fdd8 100644 --- a/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseIntegrationTests.java +++ b/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseIntegrationTests.java @@ -14,8 +14,9 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.core.License; -import org.elasticsearch.license.plugin.core.LicensesClientService; -import org.elasticsearch.license.plugin.core.LicensesService; +import org.elasticsearch.license.plugin.core.LicenseState; +import org.elasticsearch.license.plugin.core.Licensee; +import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.watcher.actions.ActionStatus; @@ -46,15 +47,13 @@ import static org.hamcrest.Matchers.*; public class LicenseIntegrationTests extends AbstractWatcherIntegrationTestCase { static final License DUMMY_LICENSE = License.builder() - .feature(LicenseService.FEATURE_NAME) .expiryDate(System.currentTimeMillis()) .issueDate(System.currentTimeMillis()) .issuedTo("LicensingTests") .issuer("test") .maxNodes(Integer.MAX_VALUE) .signature("_signature") - .type("test_license_for_watcher") - .subscriptionType("all_is_good") + .type("basic") .uid(String.valueOf(RandomizedTest.systemPropertyAsInt(SysGlobals.CHILDVM_SYSPROP_JVM_ID, 0)) + System.identityHashCode(LicenseIntegrationTests.class)) .build(); @@ -301,13 +300,13 @@ public class LicenseIntegrationTests extends AbstractWatcherIntegrationTestCase @Override protected void configure() { bind(MockLicenseService.class).asEagerSingleton(); - bind(LicensesClientService.class).to(MockLicenseService.class); + bind(LicenseeRegistry.class).to(MockLicenseService.class); } } - public static class MockLicenseService extends AbstractComponent implements LicensesClientService { + public static class MockLicenseService extends AbstractComponent implements LicenseeRegistry { - private final List listeners = new ArrayList<>(); + private final List licensees = new ArrayList<>(); @Inject public MockLicenseService(Settings settings) { @@ -316,23 +315,23 @@ public class LicenseIntegrationTests extends AbstractWatcherIntegrationTestCase } @Override - public void register(String s, LicensesService.TrialLicenseOptions trialLicenseOptions, Collection collection, AcknowledgementCallback acknowledgementCallback, Listener listener) { - listeners.add(listener); + public void register(Licensee licensee) { + licensees.add(licensee); enable(); } public void enable() { // enabled all listeners (incl. shield) - for (Listener listener : listeners) { - listener.onEnabled(DUMMY_LICENSE); + for (Licensee licensee : licensees) { + licensee.onChange(DUMMY_LICENSE, LicenseState.ENABLED); } } public void disable() { // only disable watcher listener (we need shield to work) - for (Listener listener : listeners) { - if (listener instanceof LicenseService.InternalListener) { - listener.onDisabled(DUMMY_LICENSE); + for (Licensee licensee : licensees) { + if (licensee instanceof LicenseService) { + licensee.onChange(DUMMY_LICENSE, LicenseState.DISABLED); } } }