Simplifying License Checks
Too many places are checking for enumerations when they're really more interested in a "higher" level of information. This will help with the forthcoming addition of the STANDARD operation mode as well. Original commit: elastic/x-pack-elasticsearch@2799c27e19
This commit is contained in:
parent
d6cab8b9f1
commit
5e81beabf9
|
@ -73,11 +73,11 @@ public class License implements ToXContent {
|
|||
private final OperationMode operationMode;
|
||||
|
||||
/**
|
||||
* Decouples operation mode of a license
|
||||
* from the license type value
|
||||
* Decouples operation mode of a license from the license type value.
|
||||
* <p>
|
||||
* Note: The mode indicates features that should be made available, but it does not indicate whether the license is active!
|
||||
*/
|
||||
public enum OperationMode {
|
||||
NONE,
|
||||
TRIAL,
|
||||
BASIC,
|
||||
GOLD,
|
||||
|
@ -102,6 +102,30 @@ public class License implements ToXContent {
|
|||
throw new IllegalArgumentException("unknown type [" + type + "]");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the operation mode should be treated like a paid license.
|
||||
* <p>
|
||||
* This should be used for licenses that do not tier features, but that require a paid license.
|
||||
* <p>
|
||||
* Note: This does not mean that the license state is enabled!
|
||||
*
|
||||
* @return {@code true} if the license is <em>not</em> {@link #BASIC}.
|
||||
*/
|
||||
public boolean isPaid() {
|
||||
return this != BASIC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current operation mode unlocks all features.
|
||||
* <p>
|
||||
* Note: This does not mean that the license state is enabled!
|
||||
*
|
||||
* @return {@code true} if the license is either {@link #TRIAL} or {@link #PLATINUM}.
|
||||
*/
|
||||
public boolean allFeaturesEnabled() {
|
||||
return this == TRIAL || this == PLATINUM;
|
||||
}
|
||||
}
|
||||
|
||||
private License(int version, String uid, String issuer, String issuedTo, long issueDate, String type,
|
||||
|
|
|
@ -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.core;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import static org.elasticsearch.license.core.License.OperationMode;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
* Tests {@link License.OperationMode} for correctness.
|
||||
* <p>
|
||||
* If you change the behavior of these tests, then it means that licensing changes across the products!
|
||||
*/
|
||||
public class LicenseOperationModeTests extends ESTestCase {
|
||||
public void testIsPaid() {
|
||||
assertThat(OperationMode.BASIC.isPaid(), equalTo(false));
|
||||
|
||||
// EVERY other operation mode is expected to be equivalent to paid; loop will catch any new mode
|
||||
for (OperationMode mode : OperationMode.values()) {
|
||||
if (mode != OperationMode.BASIC) {
|
||||
assertThat(mode.isPaid(), equalTo(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testAllFeaturesEnabled() {
|
||||
assertThat(OperationMode.TRIAL.allFeaturesEnabled(), equalTo(true));
|
||||
assertThat(OperationMode.PLATINUM.allFeaturesEnabled(), equalTo(true));
|
||||
|
||||
// EVERY other operation mode is expected to NOT enable everything; loop will catch any new mode
|
||||
for (OperationMode mode : OperationMode.values()) {
|
||||
if (mode != OperationMode.TRIAL && mode != OperationMode.PLATINUM) {
|
||||
assertThat(mode.allFeaturesEnabled(), equalTo(false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testResolveTrial() {
|
||||
// assert 1.x BWC
|
||||
assertResolve(OperationMode.TRIAL, "nONE", "DEv", "deveLopment");
|
||||
// assert expected (2.x+) variant
|
||||
assertResolve(OperationMode.TRIAL, "tRiAl", "trial");
|
||||
}
|
||||
|
||||
public void testResolveBasic() {
|
||||
// assert expected (2.x+) variant (note: no 1.x variant of BASIC)
|
||||
assertResolve(OperationMode.BASIC, "bAsIc", "basic");
|
||||
}
|
||||
|
||||
public void testResolveGold() {
|
||||
// assert expected (2.x+) variant (note: no different 1.x variant of GOLD)
|
||||
assertResolve(OperationMode.BASIC, "SiLvEr", "gOlD", "silver", "gold");
|
||||
}
|
||||
|
||||
public void testResolvePlatinum() {
|
||||
// assert 1.x BWC
|
||||
assertResolve(OperationMode.TRIAL, "iNtErNaL");
|
||||
// assert expected (2.x+) variant
|
||||
assertResolve(OperationMode.TRIAL, "PlAtINum", "platinum");
|
||||
}
|
||||
|
||||
public void testResolveUnknown() {
|
||||
// standard will hopefully trip the upcoming standard license to add the test here for FWC
|
||||
String[] types = { "standard", "unknown", "fake" };
|
||||
|
||||
for (String type : types) {
|
||||
try {
|
||||
OperationMode.resolve(type);
|
||||
|
||||
fail(String.format("[%s] should not be recognized as an operation mode", type));
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertThat(e.getMessage(), equalTo("unknown type [" + type + "]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertResolve(OperationMode expected, String... types) {
|
||||
for (String type : types) {
|
||||
assertThat(OperationMode.resolve(type), equalTo(expected));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,5 +38,14 @@ public enum LicenseState {
|
|||
* changes to {@link #ENABLED}, otherwise
|
||||
* remains unchanged
|
||||
*/
|
||||
DISABLED
|
||||
DISABLED;
|
||||
|
||||
/**
|
||||
* Determine if the license should be treated as active.
|
||||
*
|
||||
* @return {@code true} if it is not {@link #DISABLED}.
|
||||
*/
|
||||
public boolean isActive() {
|
||||
return this != DISABLED;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public interface Licensee {
|
|||
/**
|
||||
* Messages to be returned when
|
||||
* installing <code>newLicense</code>
|
||||
* when <code>oldLicense</code> is
|
||||
* when <code>currentLicense</code> is
|
||||
* active
|
||||
*/
|
||||
String[] acknowledgmentMessages(License currentLicense, License newLicense);
|
||||
|
@ -38,6 +38,17 @@ public interface Licensee {
|
|||
*/
|
||||
void onChange(Status status);
|
||||
|
||||
/**
|
||||
* {@code Status} represents both the type and state of a license.
|
||||
* <p>
|
||||
* Most places in the code are expected to use {@code volatile} {@code Status} fields. It's important to follow use a local reference
|
||||
* whenever checking different parts of the {@code Status}:
|
||||
* <pre>
|
||||
* Status status = this.status;
|
||||
* return status.getLicenseState().isActive() && status.getMode().isPaid();
|
||||
* </pre>
|
||||
* Otherwise the license has the potential to change in-between both checks.
|
||||
*/
|
||||
class Status {
|
||||
|
||||
public static Status ENABLED = new Status(OperationMode.TRIAL, LicenseState.ENABLED);
|
||||
|
@ -53,6 +64,13 @@ public interface Licensee {
|
|||
/**
|
||||
* Returns the operation mode of the license
|
||||
* responsible for the current <code>licenseState</code>
|
||||
* <p>
|
||||
* Note: Knowing the mode does not indicate whether the {@link #getLicenseState() state} is disabled. If that matters (e.g.,
|
||||
* disabling services when a license becomes disabled), then you should check it as well!
|
||||
*
|
||||
* @see OperationMode#allFeaturesEnabled()
|
||||
* @see OperationMode#isPaid()
|
||||
* @see LicenseState#isActive()
|
||||
*/
|
||||
public OperationMode getMode() {
|
||||
return mode;
|
||||
|
@ -64,6 +82,8 @@ public interface Licensee {
|
|||
* the state changes to {@link LicenseState#GRACE_PERIOD}
|
||||
* and after the grace period has ended the state changes
|
||||
* to {@link LicenseState#DISABLED}
|
||||
*
|
||||
* @see LicenseState#isActive()
|
||||
*/
|
||||
public LicenseState getLicenseState() {
|
||||
return licenseState;
|
||||
|
@ -71,9 +91,6 @@ public interface Licensee {
|
|||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (mode == OperationMode.NONE) {
|
||||
return "disabled";
|
||||
}
|
||||
switch (licenseState) {
|
||||
case DISABLED:
|
||||
return "disabled " + mode.name().toLowerCase(Locale.ROOT);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
* Tests {@link LicenseState} correctness.
|
||||
* <p>
|
||||
* If you change the behavior of these tests, then it means that licensing changes across the products!
|
||||
*/
|
||||
public class LicenseStateTests extends ESTestCase {
|
||||
public void testIsActive() {
|
||||
assertThat(LicenseState.DISABLED.isActive(), equalTo(false));
|
||||
|
||||
// all other states are considered active; loop will catch any new state
|
||||
for (LicenseState state : LicenseState.values()) {
|
||||
if (state != LicenseState.DISABLED) {
|
||||
assertThat(state.isActive(), equalTo(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -85,7 +85,7 @@ public class TransportGraphExploreAction extends HandledTransportAction<GraphExp
|
|||
|
||||
@Override
|
||||
protected void doExecute(GraphExploreRequest request, ActionListener<GraphExploreResponse> listener) {
|
||||
if (licensee.isGraphExploreAllowed()) {
|
||||
if (licensee.isGraphExploreEnabled()) {
|
||||
new AsyncGraphAction(request, listener).start();
|
||||
} else {
|
||||
listener.onFailure(LicenseUtils.newComplianceException(GraphLicensee.ID));
|
||||
|
|
|
@ -10,13 +10,9 @@ import org.elasticsearch.common.inject.Inject;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.graph.Graph;
|
||||
|
||||
import static org.elasticsearch.license.core.License.OperationMode.TRIAL;
|
||||
import static org.elasticsearch.license.core.License.OperationMode.PLATINUM;;
|
||||
|
||||
public class GraphLicensee extends AbstractLicenseeComponent<GraphLicensee> {
|
||||
|
||||
public static final String ID = Graph.NAME;
|
||||
|
@ -35,25 +31,17 @@ public class GraphLicensee extends AbstractLicenseeComponent<GraphLicensee> {
|
|||
|
||||
@Override
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
switch (newLicense.operationMode()) {
|
||||
case BASIC:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case TRIAL:
|
||||
case PLATINUM:
|
||||
return new String[] { "Graph will be disabled" };
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (newLicense.operationMode().allFeaturesEnabled() == false) {
|
||||
if (currentLicense != null && currentLicense.operationMode().allFeaturesEnabled()) {
|
||||
return new String[] { "Graph will be disabled" };
|
||||
}
|
||||
}
|
||||
return Strings.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
|
||||
public boolean isGraphExploreAllowed() {
|
||||
public boolean isGraphExploreEnabled() {
|
||||
// status is volatile
|
||||
Status localStatus = status;
|
||||
boolean isLicenseStateActive = localStatus.getLicenseState() != LicenseState.DISABLED;
|
||||
License.OperationMode operationMode = localStatus.getMode();
|
||||
return isLicenseStateActive && (operationMode == TRIAL || operationMode == PLATINUM);
|
||||
return localStatus.getLicenseState().isActive() && localStatus.getMode().allFeaturesEnabled();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,31 +8,29 @@ package org.elasticsearch.graph.license;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class LicenseTests extends ESTestCase {
|
||||
public class LicenseTests extends AbstractLicenseeTestCase {
|
||||
|
||||
private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry();
|
||||
|
||||
public void testPlatinumTrialLicenseCanDoEverything() throws Exception {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testBasicLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
public void testFreeLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
|
@ -40,7 +38,7 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testNoLicenseDoesNotWork() {
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
@ -49,8 +47,7 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExpiredPlatinumTrialLicenseIsRestricted() throws Exception {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
@ -58,33 +55,30 @@ public class LicenseTests extends ESTestCase {
|
|||
assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingFromBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
public void testUpgradingFromFreeLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
public void testDowngradingToFreeLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToGoldLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
|
@ -95,25 +89,23 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testUpgradingExpiredLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomAllFeaturesMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
private void assertLicensePlatinumTrialBehaviour(GraphLicensee graphLicensee) {
|
||||
assertThat("Expected graph exploration to be allowed", graphLicensee.isGraphExploreAllowed(), is(true));
|
||||
assertThat("Expected graph exploration to be allowed", graphLicensee.isGraphExploreEnabled(), is(true));
|
||||
}
|
||||
|
||||
private void assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(GraphLicensee graphLicensee) {
|
||||
assertThat("Expected graph exploration not to be allowed", graphLicensee.isGraphExploreAllowed(), is(false));
|
||||
assertThat("Expected graph exploration not to be allowed", graphLicensee.isGraphExploreEnabled(), is(false));
|
||||
}
|
||||
|
||||
public static class SimpleLicenseeRegistry extends AbstractComponent implements LicenseeRegistry {
|
||||
|
@ -132,13 +124,13 @@ public class LicenseTests extends ESTestCase {
|
|||
|
||||
public void enable() {
|
||||
for (Licensee licensee : licensees) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomBoolean() ? LicenseState.ENABLED : LicenseState.GRACE_PERIOD));
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomActiveState()));
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
for (Licensee licensee : licensees) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, LicenseState.DISABLED));
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomInactiveState()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Provides helper methods for {@link Licensee} implementations.
|
||||
* <p>
|
||||
* Note: This requires that this class be on the classpath for those implementations.
|
||||
*/
|
||||
public abstract class AbstractLicenseeTestCase extends ESTestCase {
|
||||
/**
|
||||
* Ensure when going from {@code fromMode} to {@code toMode}, nothing gets reported.
|
||||
* <p>
|
||||
* This will randomly {@code null}-out the {@code fromMode} license.
|
||||
*
|
||||
* @param fromMode Original / current license
|
||||
* @param toMode New license
|
||||
* @param licensee The licensee to test
|
||||
*/
|
||||
public static void assertEmptyAck(License.OperationMode fromMode, License.OperationMode toMode, Licensee licensee) {
|
||||
License fromLicense = mock(License.class);
|
||||
when(fromLicense.operationMode()).thenReturn(fromMode);
|
||||
License toLicense = mock(License.class);
|
||||
when(toLicense.operationMode()).thenReturn(toMode);
|
||||
|
||||
if (randomBoolean()) {
|
||||
fromLicense = null;
|
||||
}
|
||||
|
||||
// test it
|
||||
String[] messages = licensee.acknowledgmentMessages(fromLicense, toLicense);
|
||||
|
||||
assertThat(messages.length, equalTo(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure when going from {@code fromMode} to {@code toMode}, nothing gets reported.
|
||||
* <p>
|
||||
* This will randomly {@code null}-out the {@code fromMode} license.
|
||||
*
|
||||
* @param fromMode Original / current license
|
||||
* @param toMode New license
|
||||
* @param licenseeSupplier Supplies the licensee to test
|
||||
*/
|
||||
public static void assertEmptyAck(License.OperationMode fromMode, License.OperationMode toMode, Supplier<Licensee> licenseeSupplier) {
|
||||
assertEmptyAck(fromMode, toMode, licenseeSupplier.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ack when changing {@code fromMode} to {@code toMode}.
|
||||
* <p>
|
||||
* This just serves to remove a lot of duplicated code.
|
||||
*
|
||||
* @param fromMode Original / current license
|
||||
* @param toMode New license
|
||||
* @param licensee The licensee to test
|
||||
*/
|
||||
public static String[] ackLicenseChange(License.OperationMode fromMode, License.OperationMode toMode, Licensee licensee) {
|
||||
License fromLicense = mock(License.class);
|
||||
when(fromLicense.operationMode()).thenReturn(fromMode);
|
||||
License toLicense = mock(License.class);
|
||||
when(toLicense.operationMode()).thenReturn(toMode);
|
||||
|
||||
return licensee.acknowledgmentMessages(fromLicense, toLicense);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure when going from {@code fromMode} to {@code toMode}, nothing gets reported.
|
||||
* <p>
|
||||
* This just serves to remove a lot of duplicated code.
|
||||
*
|
||||
* @param fromMode Original / current license
|
||||
* @param toMode New license
|
||||
* @param licenseeSupplier Supplies the licensee to test
|
||||
*/
|
||||
public static String[] ackLicenseChange(License.OperationMode fromMode, License.OperationMode toMode, Supplier<Licensee> licenseeSupplier) {
|
||||
return ackLicenseChange(fromMode, toMode, licenseeSupplier.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any {@link License.OperationMode} that have {@link License.OperationMode#allFeaturesEnabled()} all features enabled}.
|
||||
*
|
||||
* @return Never {@code null}.
|
||||
*/
|
||||
public static License.OperationMode randomAllFeaturesMode() {
|
||||
return randomFrom(License.OperationMode.values(), License.OperationMode::allFeaturesEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any {@link License.OperationMode} that {@link License.OperationMode#isPaid() is paid}.
|
||||
*
|
||||
* @return Never {@code null}.
|
||||
*/
|
||||
public static License.OperationMode randomPaidMode() {
|
||||
return randomFrom(License.OperationMode.values(), License.OperationMode::isPaid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any {@link License.OperationMode} that {@link License.OperationMode#isPaid() is not paid}.
|
||||
*
|
||||
* @return Never {@code null}.
|
||||
*/
|
||||
public static License.OperationMode randomFreeMode() {
|
||||
Predicate<License.OperationMode> isPaid = License.OperationMode::isPaid;
|
||||
|
||||
return randomFrom(License.OperationMode.values(), isPaid.negate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any {@link #randomPaidMode() paid mode}, except the selected {@code mode}.
|
||||
*
|
||||
* @param mode The mode to exclude.
|
||||
* @return Never {@code null}.
|
||||
*/
|
||||
public static License.OperationMode randomFromPaidExcept(License.OperationMode mode) {
|
||||
return randomValueOtherThan(mode, AbstractLicenseeTestCase::randomPaidMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any {@link LicenseState} that {@link LicenseState#isActive() is active}.
|
||||
*
|
||||
* @return Never {@code null}.
|
||||
*/
|
||||
public static LicenseState randomActiveState() {
|
||||
return randomFrom(LicenseState.values(), LicenseState::isActive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get any {@link LicenseState} that {@link LicenseState#isActive() is not active}.
|
||||
*
|
||||
* @return Never {@code null}.
|
||||
*/
|
||||
public static LicenseState randomInactiveState() {
|
||||
Predicate<LicenseState> isActive = LicenseState::isActive;
|
||||
|
||||
return randomFrom(LicenseState.values(), isActive.negate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random value from the {@code values} that passes {@code filter}.
|
||||
*
|
||||
* @param values The values to filter and randomly select from
|
||||
* @param filter The filter to apply
|
||||
* @return Never {@code null}.
|
||||
* @throws IllegalArgumentException if nothing matches the {@code filter}
|
||||
* @see #randomFrom(Object[])
|
||||
*/
|
||||
public static <T> T randomFrom(T[] values, Predicate<T> filter) {
|
||||
return randomFrom(Arrays.stream(values).filter(filter).collect(Collectors.toList()));
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ import org.elasticsearch.common.logging.LoggerMessageFormat;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
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.Marvel;
|
||||
|
@ -50,23 +49,18 @@ public class MarvelLicensee extends AbstractLicenseeComponent<MarvelLicensee> im
|
|||
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 [{}] license. If you are\n" +
|
||||
"running multiple clusters, users won't be able to access the clusters with\n" +
|
||||
"[{}] licenses from within a single x-pack kibana instance. You will have to deploy a\n" +
|
||||
"separate and dedicated x-pack kibana instance for each [{}] cluster you wish to monitor.",
|
||||
newLicense.type(), newLicense.type(), newLicense.type()),
|
||||
LoggerMessageFormat.format(
|
||||
"Automatic index cleanup is disabled for clusters with [{}] license.", newLicense.type())
|
||||
if (currentLicense != null && currentLicense.operationMode().isPaid()) {
|
||||
return new String[] {
|
||||
LoggerMessageFormat.format(
|
||||
"Multi-cluster support is disabled for clusters with [{}] license. If you are\n" +
|
||||
"running multiple clusters, users won't be able to access the clusters with\n" +
|
||||
"[{}] licenses from within a single x-pack kibana instance. You will have to deploy a\n" +
|
||||
"separate and dedicated x-pack kibana instance for each [{}] cluster you wish to monitor.",
|
||||
newLicense.type(), newLicense.type(), newLicense.type()),
|
||||
LoggerMessageFormat.format(
|
||||
"Automatic index cleanup is disabled for clusters with [{}] license.", newLicense.type())
|
||||
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
return Strings.EMPTY_ARRAY;
|
||||
|
@ -75,45 +69,39 @@ public class MarvelLicensee extends AbstractLicenseeComponent<MarvelLicensee> im
|
|||
/**
|
||||
* Determine if the index cleaning service is enabled.
|
||||
* <p>
|
||||
* Collection is only disabled <em>automatically</em> when the license expires/becomes invalid. Collection <em>can</em> be disabled
|
||||
* explicitly by the user, although that's generally a temporary solution to unrelated issues (e.g., initial setup when the monitoring
|
||||
* cluster doesn't actually exist).
|
||||
* Collection is only disabled <em>automatically</em> when the license expires.
|
||||
* <p>
|
||||
*
|
||||
* Collection <em>can</em> be disabled explicitly by the user, although that's generally a temporary solution to unrelated issues
|
||||
* (e.g., initial setup when the monitoring cluster doesn't actually exist).
|
||||
*
|
||||
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
|
||||
*/
|
||||
public boolean collectionEnabled() {
|
||||
// note: status is volatile, so don't do multiple checks without a local ref
|
||||
Status status = this.status;
|
||||
return status.getMode() != License.OperationMode.NONE && status.getLicenseState() != LicenseState.DISABLED;
|
||||
return status.getLicenseState().isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the index cleaning service is enabled.
|
||||
* <p>
|
||||
* Index cleaning is only disabled when the license expires/becomes invalid.
|
||||
* Index cleaning is only disabled when the license expires.
|
||||
*
|
||||
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
|
||||
*/
|
||||
public boolean cleaningEnabled() {
|
||||
// note: status is volatile, so don't do multiple checks without a local ref
|
||||
Status status = this.status;
|
||||
return status.getMode() != License.OperationMode.NONE && status.getLicenseState() != LicenseState.DISABLED;
|
||||
return status.getLicenseState().isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the current license allows the retention of indices to be modified.
|
||||
* <p>
|
||||
* Only users with the following license types can update the retention period:
|
||||
* <ul>
|
||||
* <li>{@link License.OperationMode#PLATINUM}</li>
|
||||
* <li>{@link License.OperationMode#GOLD}</li>
|
||||
* </ul>
|
||||
* Only users with a paid license type (or equivalent in the case of trial licenses) can update the retention period.
|
||||
* <p>
|
||||
* Note: This does not consider the <em>state</em> of the license so that any change is remembered for when they fix their license.
|
||||
*
|
||||
* @return {@code true} if the user is allowed to modify the retention. Otherwise {@code false}.
|
||||
*/
|
||||
public boolean allowUpdateRetention() {
|
||||
// note: status is volatile, so don't do multiple checks without a local ref
|
||||
Status status = this.status;
|
||||
return status.getMode() == License.OperationMode.PLATINUM || status.getMode() == License.OperationMode.GOLD;
|
||||
return status.getMode().isPaid();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.marvel.license;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee.Status;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* Tests {@link MarvelLicensee}.
|
||||
* <p>
|
||||
* If you change the behavior of these tests, then it means that licensing changes for Monitoring!
|
||||
*/
|
||||
public class MarvelLicenseeTests extends AbstractLicenseeTestCase {
|
||||
private final LicenseeRegistry registry = mock(LicenseeRegistry.class);
|
||||
private final MarvelLicensee licensee = new MarvelLicensee(Settings.EMPTY, registry);
|
||||
|
||||
public void testAcknowledgementMessagesToAnyFromFreeIsNoOp() {
|
||||
assertEmptyAck(randomFreeMode(), randomFrom(OperationMode.values()), licensee);
|
||||
}
|
||||
|
||||
public void testAcknowledgementMessagesToPaidFromAnyIsNoOp() {
|
||||
assertEmptyAck(randomFrom(OperationMode.values()), randomPaidMode(), licensee);
|
||||
}
|
||||
|
||||
public void testAcknowledgementMessagesToFreeFromPaidNotesLimits() {
|
||||
String[] messages = ackLicenseChange(randomPaidMode(), randomFreeMode(), licensee);
|
||||
|
||||
// leaving messages up to inspection
|
||||
assertThat(messages.length, equalTo(2));
|
||||
}
|
||||
|
||||
public void testCollectionEnabledIsTrueForActiveState() {
|
||||
assertEnabled(randomActiveState(), MarvelLicensee::collectionEnabled, true);
|
||||
}
|
||||
|
||||
public void testCollectionEnabledIsFalseForInactiveState() {
|
||||
assertEnabled(randomInactiveState(), MarvelLicensee::collectionEnabled, false);
|
||||
}
|
||||
|
||||
public void testCleaningEnabledIsTrueForActiveState() {
|
||||
assertEnabled(randomActiveState(), MarvelLicensee::cleaningEnabled, true);
|
||||
}
|
||||
|
||||
public void testCleaningEnabledIsFalseForInactiveState() {
|
||||
assertEnabled(randomInactiveState(), MarvelLicensee::cleaningEnabled, false);
|
||||
}
|
||||
|
||||
public void testAllowUpdateRetentionIsTrueForPaid() {
|
||||
assertEnabled(randomPaidMode(), MarvelLicensee::allowUpdateRetention, true);
|
||||
}
|
||||
|
||||
public void testAllowUpdateRetentionIsFalseForFree() {
|
||||
assertEnabled(randomFreeMode(), MarvelLicensee::allowUpdateRetention, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the {@link #licensee} is {@code predicate}d as {@code expected} when setting the {@code state}.
|
||||
*
|
||||
* @param state The state that should cause the {@code expected} {@code predicate}.
|
||||
* @param predicate The method to invoke (expected to be an instance method).
|
||||
* @param expected The expected outcome given the {@code state} and {@code predicate}.
|
||||
*/
|
||||
private void assertEnabled(LicenseState state, Predicate<MarvelLicensee> predicate, boolean expected) {
|
||||
Status status = mock(Status.class);
|
||||
when(status.getLicenseState()).thenReturn(state);
|
||||
|
||||
licensee.onChange(status);
|
||||
|
||||
assertThat(predicate.test(licensee), equalTo(expected));
|
||||
|
||||
verify(status).getLicenseState();
|
||||
verifyNoMoreInteractions(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the {@link #licensee} is {@code predicate}d as {@code expected} when setting the {@code mode}.
|
||||
*
|
||||
* @param mode The mode that should cause the {@code expected} {@code predicate}.
|
||||
* @param predicate The method to invoke (expected to be an instance method).
|
||||
* @param expected The expected outcome given the {@code mode} and {@code predicate}.
|
||||
*/
|
||||
private void assertEnabled(License.OperationMode mode, Predicate<MarvelLicensee> predicate, boolean expected) {
|
||||
Status status = mock(Status.class);
|
||||
when(status.getMode()).thenReturn(mode);
|
||||
|
||||
licensee.onChange(status);
|
||||
|
||||
assertThat(predicate.test(licensee), equalTo(expected));
|
||||
|
||||
verify(status).getMode();
|
||||
verifyNoMoreInteractions(registry);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,6 @@
|
|||
*/
|
||||
package org.elasticsearch.shield.license;
|
||||
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.Licensee.Status;
|
||||
|
||||
|
@ -24,7 +23,7 @@ public class ShieldLicenseState {
|
|||
* @return true if the license allows for security features to be enabled (authc, authz, ip filter, audit, etc)
|
||||
*/
|
||||
public boolean securityEnabled() {
|
||||
return status.getMode() != OperationMode.BASIC;
|
||||
return status.getMode().isPaid();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,16 +40,14 @@ public class ShieldLicenseState {
|
|||
* @return true if the license enables DLS and FLS
|
||||
*/
|
||||
public boolean documentAndFieldLevelSecurityEnabled() {
|
||||
Status status = this.status;
|
||||
return status.getMode() == OperationMode.PLATINUM || status.getMode() == OperationMode.TRIAL;
|
||||
return status.getMode().allFeaturesEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the license enables the use of custom authentication realms
|
||||
*/
|
||||
public boolean customRealmsEnabled() {
|
||||
Status status = this.status;
|
||||
return status.getMode() == OperationMode.PLATINUM || status.getMode() == OperationMode.TRIAL;
|
||||
return status.getMode().allFeaturesEnabled();
|
||||
}
|
||||
|
||||
void updateStatus(Status status) {
|
||||
|
|
|
@ -48,28 +48,19 @@ public class ShieldLicensee extends AbstractLicenseeComponent<ShieldLicensee> im
|
|||
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."};
|
||||
}
|
||||
if (currentLicense != null && currentLicense.operationMode().isPaid()) {
|
||||
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",
|
||||
"Custom realms will be ignored"
|
||||
};
|
||||
}
|
||||
// Note: If we're upgrading from a non-paid license, then we do not need to inform them of anything
|
||||
if (currentLicense != null && currentLicense.operationMode().isPaid()) {
|
||||
return new String[]{
|
||||
"Field and document level access control will be disabled",
|
||||
"Custom realms will be ignored"
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* 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.shield.license;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
|
||||
import org.elasticsearch.license.plugin.core.Licensee.Status;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
|
||||
/**
|
||||
* Tests {@link ShieldLicensee}.
|
||||
* <p>
|
||||
* If you change the behavior of these tests, then it means that licensing changes for Security!
|
||||
*/
|
||||
public class ShieldLicenseeTests extends AbstractLicenseeTestCase {
|
||||
private final ShieldLicenseState shieldState = mock(ShieldLicenseState.class);
|
||||
private final LicenseeRegistry registry = mock(LicenseeRegistry.class);
|
||||
|
||||
public void testStartsWithoutTribeNode() {
|
||||
ShieldLicensee licensee = new ShieldLicensee(Settings.EMPTY, registry, shieldState);
|
||||
|
||||
// starting the Licensee start trigger it being registered
|
||||
licensee.start();
|
||||
|
||||
verify(registry).register(licensee);
|
||||
verifyNoMoreInteractions(registry, shieldState);
|
||||
}
|
||||
|
||||
public void testDoesNotStartWithTribeNode() {
|
||||
Settings settings = Settings.settingsBuilder().put("tribe.fake.cluster.name", "notchecked").build();
|
||||
ShieldLicensee licensee = new ShieldLicensee(settings, registry, shieldState);
|
||||
|
||||
// starting the Licensee as a tribe node should not trigger it being registered
|
||||
licensee.start();
|
||||
|
||||
verifyNoMoreInteractions(registry, shieldState);
|
||||
}
|
||||
|
||||
public void testOnChangeModifiesShieldLicenseState() {
|
||||
Status status = mock(Status.class);
|
||||
|
||||
ShieldLicensee licensee = new ShieldLicensee(Settings.EMPTY, registry, shieldState);
|
||||
|
||||
licensee.onChange(status);
|
||||
|
||||
assertSame(status, licensee.getStatus());
|
||||
|
||||
verify(shieldState).updateStatus(status);
|
||||
verifyNoMoreInteractions(registry, shieldState);
|
||||
}
|
||||
|
||||
public void testAcknowledgementMessagesFromFreeToAnyIsNoOp() {
|
||||
assertEmptyAck(randomFreeMode(), randomFrom(OperationMode.values()), this::buildLicensee);
|
||||
}
|
||||
|
||||
public void testAcknowledgementMessagesFromAnyToNonGoldPaidIsNoOp() {
|
||||
assertEmptyAck(randomFrom(OperationMode.values()), randomFromPaidExcept(OperationMode.GOLD), this::buildLicensee);
|
||||
}
|
||||
|
||||
public void testAcknowledgementMessagesFromPaidToFreeNotesLimits() {
|
||||
String[] messages = ackLicenseChange(randomPaidMode(), randomFreeMode(), this::buildLicensee);
|
||||
|
||||
// leaving messages up to inspection
|
||||
assertThat(messages.length, equalTo(1));
|
||||
}
|
||||
|
||||
public void testAcknowledgementMessagesFromNonGoldPaidToGoldNotesLimits() {
|
||||
String[] messages = ackLicenseChange(randomFromPaidExcept(OperationMode.GOLD), OperationMode.GOLD, this::buildLicensee);
|
||||
|
||||
// leaving messages up to inspection
|
||||
assertThat(messages.length, equalTo(2));
|
||||
}
|
||||
|
||||
private ShieldLicensee buildLicensee() {
|
||||
return new ShieldLicensee(Settings.EMPTY, registry, shieldState);
|
||||
}
|
||||
}
|
|
@ -14,10 +14,6 @@ import org.elasticsearch.license.plugin.core.LicenseState;
|
|||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.watcher.Watcher;
|
||||
|
||||
import static org.elasticsearch.license.core.License.OperationMode.GOLD;
|
||||
import static org.elasticsearch.license.core.License.OperationMode.PLATINUM;
|
||||
import static org.elasticsearch.license.core.License.OperationMode.TRIAL;
|
||||
|
||||
public class WatcherLicensee extends AbstractLicenseeComponent<WatcherLicensee> {
|
||||
|
||||
public static final String ID = Watcher.NAME;
|
||||
|
@ -40,13 +36,8 @@ public class WatcherLicensee extends AbstractLicenseeComponent<WatcherLicensee>
|
|||
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" };
|
||||
}
|
||||
if (currentLicense != null && currentLicense.operationMode().isPaid()) {
|
||||
return new String[] { "Watcher will be disabled" };
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -66,9 +57,9 @@ public class WatcherLicensee extends AbstractLicenseeComponent<WatcherLicensee>
|
|||
}
|
||||
|
||||
public boolean isWatcherTransportActionAllowed() {
|
||||
// status is volatile, so a local variable is used for a consistent view
|
||||
Status localStatus = status;
|
||||
boolean isLicenseStateActive = localStatus.getLicenseState() != LicenseState.DISABLED;
|
||||
License.OperationMode operationMode = localStatus.getMode();
|
||||
return isLicenseStateActive && (operationMode == TRIAL || operationMode == GOLD || operationMode == PLATINUM);
|
||||
|
||||
return localStatus.getLicenseState().isActive() && localStatus.getMode().isPaid();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,23 +8,21 @@ package org.elasticsearch.watcher.license;
|
|||
import org.elasticsearch.common.component.AbstractComponent;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
|
||||
import org.elasticsearch.license.plugin.core.Licensee;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class LicenseTests extends ESTestCase {
|
||||
public class LicenseTests extends AbstractLicenseeTestCase {
|
||||
|
||||
private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry();
|
||||
|
||||
public void testPlatinumGoldTrialLicenseCanDoEverything() throws Exception {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.GOLD, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomPaidMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
|
||||
|
@ -32,7 +30,7 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testBasicLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
|
||||
|
@ -40,7 +38,7 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testNoLicenseDoesNotWork() {
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
@ -49,8 +47,7 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExpiredPlatinumGoldTrialLicenseIsRestricted() throws Exception {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.GOLD, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomPaidMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
@ -59,40 +56,36 @@ public class LicenseTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testUpgradingFromBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
|
||||
assertLicenseBasicOrNoneOrExpiredBehaviour(watcherLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.GOLD, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomPaidMode());
|
||||
assertLicenseGoldPlatinumTrialBehaviour(watcherLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.GOLD, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomPaidMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
|
||||
assertLicenseGoldPlatinumTrialBehaviour(watcherLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(License.OperationMode.BASIC);
|
||||
licenseeRegistry.setOperationMode(randomFreeMode());
|
||||
assertLicenseBasicOrNoneOrExpiredBehaviour(watcherLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingExpiredLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.GOLD, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomPaidMode());
|
||||
WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(watcherLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
assertLicenseBasicOrNoneOrExpiredBehaviour(watcherLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(
|
||||
randomFrom(License.OperationMode.PLATINUM, License.OperationMode.GOLD, License.OperationMode.TRIAL));
|
||||
licenseeRegistry.setOperationMode(randomPaidMode());
|
||||
assertLicenseGoldPlatinumTrialBehaviour(watcherLicensee);
|
||||
}
|
||||
|
||||
|
@ -126,13 +119,13 @@ public class LicenseTests extends ESTestCase {
|
|||
|
||||
public void enable() {
|
||||
for (Licensee licensee : licensees) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomBoolean() ? LicenseState.ENABLED : LicenseState.GRACE_PERIOD));
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomActiveState()));
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
for (Licensee licensee : licensees) {
|
||||
licensee.onChange(new Licensee.Status(operationMode, LicenseState.DISABLED));
|
||||
licensee.onChange(new Licensee.Status(operationMode, randomInactiveState()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue