diff --git a/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java index 37c410d0a55..97f0a3a23b2 100644 --- a/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java +++ b/elasticsearch/license/base/src/main/java/org/elasticsearch/license/core/License.java @@ -102,30 +102,6 @@ public class License implements ToXContent { throw new IllegalArgumentException("unknown type [" + type + "]"); } } - - /** - * Determine if the operation mode should be treated like a paid license. - *

- * This should be used for licenses that do not tier features, but that require a paid license. - *

- * Note: This does not mean that the license state is enabled! - * - * @return {@code true} if the license is not {@link #BASIC}. - */ - public boolean isPaid() { - return this != BASIC; - } - - /** - * Determine if the current operation mode unlocks all features. - *

- * 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, diff --git a/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseOperationModeTests.java b/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseOperationModeTests.java index 827533ba246..9eaf477169a 100644 --- a/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseOperationModeTests.java +++ b/elasticsearch/license/base/src/test/java/org/elasticsearch/license/core/LicenseOperationModeTests.java @@ -16,29 +16,6 @@ import static org.hamcrest.Matchers.equalTo; * 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"); @@ -53,14 +30,14 @@ public class LicenseOperationModeTests extends ESTestCase { public void testResolveGold() { // assert expected (2.x+) variant (note: no different 1.x variant of GOLD) - assertResolve(OperationMode.BASIC, "SiLvEr", "gOlD", "silver", "gold"); + assertResolve(OperationMode.GOLD, "SiLvEr", "gOlD", "silver", "gold"); } public void testResolvePlatinum() { // assert 1.x BWC - assertResolve(OperationMode.TRIAL, "iNtErNaL"); + assertResolve(OperationMode.PLATINUM, "iNtErNaL"); // assert expected (2.x+) variant - assertResolve(OperationMode.TRIAL, "PlAtINum", "platinum"); + assertResolve(OperationMode.PLATINUM, "PlAtINum", "platinum"); } public void testResolveUnknown() { diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java index 9e5b39cad16..a6eba86c532 100644 --- a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/LicenseState.java @@ -38,14 +38,5 @@ public enum LicenseState { * changes to {@link #ENABLED}, otherwise * remains unchanged */ - 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; - } + DISABLED } diff --git a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java index ec557c5aad8..27432b4ce8c 100644 --- a/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java +++ b/elasticsearch/license/plugin-api/src/main/java/org/elasticsearch/license/plugin/core/Licensee.java @@ -67,10 +67,6 @@ public interface Licensee { *

* 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; @@ -82,8 +78,6 @@ 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; diff --git a/elasticsearch/license/plugin-api/src/test/java/org/elasticsearch/license/plugin/core/LicenseStateTests.java b/elasticsearch/license/plugin-api/src/test/java/org/elasticsearch/license/plugin/core/LicenseStateTests.java deleted file mode 100644 index dfef24e499e..00000000000 --- a/elasticsearch/license/plugin-api/src/test/java/org/elasticsearch/license/plugin/core/LicenseStateTests.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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. - *

- * 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)); - } - } - } -} diff --git a/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/license/GraphLicensee.java b/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/license/GraphLicensee.java index 15996f64266..5b6e66ec8e8 100644 --- a/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/license/GraphLicensee.java +++ b/elasticsearch/x-pack/graph/src/main/java/org/elasticsearch/graph/license/GraphLicensee.java @@ -9,7 +9,9 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; 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.AbstractLicenseeComponent; +import org.elasticsearch.license.plugin.core.LicenseState; import org.elasticsearch.license.plugin.core.LicenseeRegistry; import org.elasticsearch.graph.Graph; @@ -31,17 +33,39 @@ public class GraphLicensee extends AbstractLicenseeComponent { @Override public String[] acknowledgmentMessages(License currentLicense, License newLicense) { - if (newLicense.operationMode().allFeaturesEnabled() == false) { - if (currentLicense != null && currentLicense.operationMode().allFeaturesEnabled()) { - return new String[] { "Graph will be disabled" }; - } + switch (newLicense.operationMode()) { + case BASIC: + case GOLD: + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case TRIAL: + case PLATINUM: + return new String[] { "Graph will be disabled" }; + } + } + break; } return Strings.EMPTY_ARRAY; } + /** + * Determine if Graph Exploration should be enabled. + *

+ * Exploration is only disabled when the license has expired or if the mode is not: + *

+ * + * @return {@code true} as long as the license is valid. Otherwise {@code false}. + */ public boolean isGraphExploreEnabled() { // status is volatile Status localStatus = status; - return localStatus.getLicenseState().isActive() && localStatus.getMode().allFeaturesEnabled(); + OperationMode operationMode = localStatus.getMode(); + + boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM; + + return licensed && localStatus.getLicenseState() != LicenseState.DISABLED; } } diff --git a/elasticsearch/x-pack/graph/src/test/java/org/elasticsearch/graph/license/LicenseTests.java b/elasticsearch/x-pack/graph/src/test/java/org/elasticsearch/graph/license/LicenseTests.java index 712d0704708..ebf339b7d88 100644 --- a/elasticsearch/x-pack/graph/src/test/java/org/elasticsearch/graph/license/LicenseTests.java +++ b/elasticsearch/x-pack/graph/src/test/java/org/elasticsearch/graph/license/LicenseTests.java @@ -5,15 +5,9 @@ */ 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.core.License.OperationMode; import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase; -import org.elasticsearch.license.plugin.core.Licensee; -import org.elasticsearch.license.plugin.core.LicenseeRegistry; - -import java.util.ArrayList; -import java.util.List; import static org.hamcrest.Matchers.is; @@ -22,15 +16,15 @@ public class LicenseTests extends AbstractLicenseeTestCase { private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry(); public void testPlatinumTrialLicenseCanDoEverything() throws Exception { - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); assertLicensePlatinumTrialBehaviour(graphLicensee); } - public void testFreeLicenseIsDisabled() throws Exception { - licenseeRegistry.setOperationMode(randomFreeMode()); + public void testBasicLicenseIsDisabled() throws Exception { + licenseeRegistry.setOperationMode(OperationMode.BASIC); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); @@ -38,7 +32,7 @@ public class LicenseTests extends AbstractLicenseeTestCase { } public void testNoLicenseDoesNotWork() { - licenseeRegistry.setOperationMode(randomFreeMode()); + licenseeRegistry.setOperationMode(OperationMode.BASIC); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); licenseeRegistry.disable(); @@ -47,7 +41,7 @@ public class LicenseTests extends AbstractLicenseeTestCase { } public void testExpiredPlatinumTrialLicenseIsRestricted() throws Exception { - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); licenseeRegistry.disable(); @@ -55,48 +49,48 @@ public class LicenseTests extends AbstractLicenseeTestCase { assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee); } - public void testUpgradingFromFreeLicenseWorks() { - licenseeRegistry.setOperationMode(randomFreeMode()); + public void testUpgradingFromBasicLicenseWorks() { + licenseeRegistry.setOperationMode(OperationMode.BASIC); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee); - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); assertLicensePlatinumTrialBehaviour(graphLicensee); } - public void testDowngradingToFreeLicenseWorks() { - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + public void testDowngradingToBasicLicenseWorks() { + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); assertLicensePlatinumTrialBehaviour(graphLicensee); - licenseeRegistry.setOperationMode(randomFreeMode()); + licenseeRegistry.setOperationMode(OperationMode.BASIC); assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee); } public void testDowngradingToGoldLicenseWorks() { - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); assertLicensePlatinumTrialBehaviour(graphLicensee); - licenseeRegistry.setOperationMode(License.OperationMode.GOLD); + licenseeRegistry.setOperationMode(OperationMode.GOLD); assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee); } public void testUpgradingExpiredLicenseWorks() { - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(graphLicensee); licenseeRegistry.disable(); assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(graphLicensee); - licenseeRegistry.setOperationMode(randomAllFeaturesMode()); + licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode()); assertLicensePlatinumTrialBehaviour(graphLicensee); } @@ -107,36 +101,4 @@ public class LicenseTests extends AbstractLicenseeTestCase { private void assertLicenseBasicOrGoldOrNoneOrExpiredBehaviour(GraphLicensee graphLicensee) { assertThat("Expected graph exploration not to be allowed", graphLicensee.isGraphExploreEnabled(), is(false)); } - - public static class SimpleLicenseeRegistry extends AbstractComponent implements LicenseeRegistry { - private final List licensees = new ArrayList<>(); - private License.OperationMode operationMode; - - public SimpleLicenseeRegistry() { - super(Settings.EMPTY); - } - - @Override - public void register(Licensee licensee) { - licensees.add(licensee); - enable(); - } - - public void enable() { - for (Licensee licensee : licensees) { - licensee.onChange(new Licensee.Status(operationMode, randomActiveState())); - } - } - - public void disable() { - for (Licensee licensee : licensees) { - licensee.onChange(new Licensee.Status(operationMode, randomInactiveState())); - } - } - - public void setOperationMode(License.OperationMode operationMode) { - this.operationMode = operationMode; - enable(); - } - } } diff --git a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/AbstractLicenseeTestCase.java b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/AbstractLicenseeTestCase.java index 7be8cb2eadd..1a8eedd98c4 100644 --- a/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/AbstractLicenseeTestCase.java +++ b/elasticsearch/x-pack/license-plugin/src/test/java/org/elasticsearch/license/plugin/core/AbstractLicenseeTestCase.java @@ -5,10 +5,15 @@ */ package org.elasticsearch.license.plugin.core; +import org.elasticsearch.common.component.AbstractComponent; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.core.License; +import org.elasticsearch.license.core.License.OperationMode; import org.elasticsearch.test.ESTestCase; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -32,7 +37,7 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase { * @param toMode New license * @param licensee The licensee to test */ - public static void assertEmptyAck(License.OperationMode fromMode, License.OperationMode toMode, Licensee licensee) { + public static void assertEmptyAck(OperationMode fromMode, OperationMode toMode, Licensee licensee) { License fromLicense = mock(License.class); when(fromLicense.operationMode()).thenReturn(fromMode); License toLicense = mock(License.class); @@ -57,7 +62,7 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase { * @param toMode New license * @param licenseeSupplier Supplies the licensee to test */ - public static void assertEmptyAck(License.OperationMode fromMode, License.OperationMode toMode, Supplier licenseeSupplier) { + public static void assertEmptyAck(OperationMode fromMode, OperationMode toMode, Supplier licenseeSupplier) { assertEmptyAck(fromMode, toMode, licenseeSupplier.get()); } @@ -70,7 +75,7 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase { * @param toMode New license * @param licensee The licensee to test */ - public static String[] ackLicenseChange(License.OperationMode fromMode, License.OperationMode toMode, Licensee licensee) { + public static String[] ackLicenseChange(OperationMode fromMode, OperationMode toMode, Licensee licensee) { License fromLicense = mock(License.class); when(fromLicense.operationMode()).thenReturn(fromMode); License toLicense = mock(License.class); @@ -88,67 +93,54 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase { * @param toMode New license * @param licenseeSupplier Supplies the licensee to test */ - public static String[] ackLicenseChange(License.OperationMode fromMode, License.OperationMode toMode, Supplier licenseeSupplier) { + public static String[] ackLicenseChange(OperationMode fromMode, OperationMode toMode, Supplier licenseeSupplier) { return ackLicenseChange(fromMode, toMode, licenseeSupplier.get()); } /** - * Get any {@link License.OperationMode} that have {@link License.OperationMode#allFeaturesEnabled()} all features enabled}. + * Randomly get {@link OperationMode#TRIAL} or {@link OperationMode#PLATINUM}. * * @return Never {@code null}. */ - public static License.OperationMode randomAllFeaturesMode() { - return randomFrom(License.OperationMode.values(), License.OperationMode::allFeaturesEnabled); + public static OperationMode randomTrialOrPlatinumMode() { + return randomFrom(OperationMode.TRIAL, OperationMode.PLATINUM); } /** - * Get any {@link License.OperationMode} that {@link License.OperationMode#isPaid() is paid}. + * Randomly get {@link OperationMode#TRIAL}, {@link OperationMode#GOLD}, or {@link OperationMode#PLATINUM}. * * @return Never {@code null}. */ - public static License.OperationMode randomPaidMode() { - return randomFrom(License.OperationMode.values(), License.OperationMode::isPaid); + public static OperationMode randomTrialGoldOrPlatinumMode() { + return randomFrom(OperationMode.TRIAL, OperationMode.GOLD, OperationMode.PLATINUM); } /** - * Get any {@link License.OperationMode} that {@link License.OperationMode#isPaid() is not paid}. + * Randomly get any {@link OperationMode}. * * @return Never {@code null}. */ - public static License.OperationMode randomFreeMode() { - Predicate isPaid = License.OperationMode::isPaid; - - return randomFrom(License.OperationMode.values(), isPaid.negate()); + public static OperationMode randomMode() { + return randomFrom(OperationMode.values()); } /** - * Get any {@link #randomPaidMode() paid mode}, except the selected {@code mode}. + * Get any {@link #randomMode() 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); + public static OperationMode randomModeExcept(OperationMode mode) { + return randomValueOtherThan(mode, AbstractLicenseeTestCase::randomMode); } /** - * Get any {@link LicenseState} that {@link LicenseState#isActive() is active}. + * Randomly get {@link LicenseState#ENABLED} or {@link LicenseState#GRACE_PERIOD}. * * @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 isActive = LicenseState::isActive; - - return randomFrom(LicenseState.values(), isActive.negate()); + public static LicenseState randomEnabledOrGracePeriodState() { + return randomFrom(LicenseState.ENABLED, LicenseState.GRACE_PERIOD); } /** @@ -163,4 +155,36 @@ public abstract class AbstractLicenseeTestCase extends ESTestCase { public static T randomFrom(T[] values, Predicate filter) { return randomFrom(Arrays.stream(values).filter(filter).collect(Collectors.toList())); } + + public static class SimpleLicenseeRegistry extends AbstractComponent implements LicenseeRegistry { + private final List licensees = new ArrayList<>(); + private OperationMode operationMode; + + public SimpleLicenseeRegistry() { + super(Settings.EMPTY); + } + + @Override + public void register(Licensee licensee) { + licensees.add(licensee); + enable(); + } + + public void enable() { + for (Licensee licensee : licensees) { + licensee.onChange(new Licensee.Status(operationMode, randomEnabledOrGracePeriodState())); + } + } + + public void disable() { + for (Licensee licensee : licensees) { + licensee.onChange(new Licensee.Status(operationMode, LicenseState.DISABLED)); + } + } + + public void setOperationMode(License.OperationMode operationMode) { + this.operationMode = operationMode; + enable(); + } + } } diff --git a/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java index 7402f1869cb..d435366320f 100644 --- a/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java +++ b/elasticsearch/x-pack/marvel/src/main/java/org/elasticsearch/marvel/license/MarvelLicensee.java @@ -10,7 +10,9 @@ import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.logging.LoggerMessageFormat; 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.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; @@ -49,19 +51,24 @@ public class MarvelLicensee extends AbstractLicenseeComponent im public String[] acknowledgmentMessages(License currentLicense, License newLicense) { switch (newLicense.operationMode()) { case BASIC: - 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()) - - }; + 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()) + }; + } } + break; } return Strings.EMPTY_ARRAY; } @@ -69,39 +76,42 @@ public class MarvelLicensee extends AbstractLicenseeComponent im /** * Determine if the index cleaning service is enabled. *

- * Collection is only disabled automatically when the license expires. + * Collection is only disabled automatically when the license expires. All modes are valid for collection. *

- * * Collection can 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() { - return status.getLicenseState().isActive(); + return status.getLicenseState() != LicenseState.DISABLED; } /** * Determine if the index cleaning service is enabled. *

- * Index cleaning is only disabled when the license expires. + * Index cleaning is only disabled when the license expires. All modes are valid for cleaning. * * @return {@code true} as long as the license is valid. Otherwise {@code false}. */ public boolean cleaningEnabled() { - return status.getLicenseState().isActive(); + return status.getLicenseState() != LicenseState.DISABLED; } /** * Determine if the current license allows the retention of indices to be modified. *

- * Only users with a paid license type (or equivalent in the case of trial licenses) can update the retention period. - *

+ * Only users with the following license types can update the retention period: + *

    + *
  • {@link OperationMode#PLATINUM}
  • + *
  • {@link OperationMode#GOLD}
  • + *
  • {@link OperationMode#TRIAL}
  • + *
* Note: This does not consider the state 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() { - return status.getMode().isPaid(); + return status.getMode() != OperationMode.BASIC; } } diff --git a/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/MarvelLicenseeTests.java b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/MarvelLicenseeTests.java index 9c9ce10ed7b..ea7754bebe0 100644 --- a/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/MarvelLicenseeTests.java +++ b/elasticsearch/x-pack/marvel/src/test/java/org/elasticsearch/marvel/license/MarvelLicenseeTests.java @@ -31,42 +31,42 @@ public class MarvelLicenseeTests extends AbstractLicenseeTestCase { private final MarvelLicensee licensee = new MarvelLicensee(Settings.EMPTY, registry); public void testAcknowledgementMessagesToAnyFromFreeIsNoOp() { - assertEmptyAck(randomFreeMode(), randomFrom(OperationMode.values()), licensee); + assertEmptyAck(OperationMode.BASIC, randomMode(), licensee); } - public void testAcknowledgementMessagesToPaidFromAnyIsNoOp() { - assertEmptyAck(randomFrom(OperationMode.values()), randomPaidMode(), licensee); + public void testAcknowledgementMessagesToTrialGoldOrPlatinumFromAnyIsNoOp() { + assertEmptyAck(randomMode(), randomTrialGoldOrPlatinumMode(), licensee); } - public void testAcknowledgementMessagesToFreeFromPaidNotesLimits() { - String[] messages = ackLicenseChange(randomPaidMode(), randomFreeMode(), licensee); + public void testAcknowledgementMessagesToBasicFromNotBasicNotesLimits() { + String[] messages = ackLicenseChange(randomModeExcept(OperationMode.BASIC), OperationMode.BASIC, licensee); // leaving messages up to inspection assertThat(messages.length, equalTo(2)); } public void testCollectionEnabledIsTrueForActiveState() { - assertEnabled(randomActiveState(), MarvelLicensee::collectionEnabled, true); + assertEnabled(randomEnabledOrGracePeriodState(), MarvelLicensee::collectionEnabled, true); } public void testCollectionEnabledIsFalseForInactiveState() { - assertEnabled(randomInactiveState(), MarvelLicensee::collectionEnabled, false); + assertEnabled(LicenseState.DISABLED, MarvelLicensee::collectionEnabled, false); } public void testCleaningEnabledIsTrueForActiveState() { - assertEnabled(randomActiveState(), MarvelLicensee::cleaningEnabled, true); + assertEnabled(randomEnabledOrGracePeriodState(), MarvelLicensee::cleaningEnabled, true); } public void testCleaningEnabledIsFalseForInactiveState() { - assertEnabled(randomInactiveState(), MarvelLicensee::cleaningEnabled, false); + assertEnabled(LicenseState.DISABLED, MarvelLicensee::cleaningEnabled, false); } - public void testAllowUpdateRetentionIsTrueForPaid() { - assertEnabled(randomPaidMode(), MarvelLicensee::allowUpdateRetention, true); + public void testAllowUpdateRetentionIsTrueForNotBasic() { + assertEnabled(randomModeExcept(OperationMode.BASIC), MarvelLicensee::allowUpdateRetention, true); } - public void testAllowUpdateRetentionIsFalseForFree() { - assertEnabled(randomFreeMode(), MarvelLicensee::allowUpdateRetention, false); + public void testAllowUpdateRetentionIsFalseForBasic() { + assertEnabled(OperationMode.BASIC, MarvelLicensee::allowUpdateRetention, false); } /** @@ -95,7 +95,7 @@ public class MarvelLicenseeTests extends AbstractLicenseeTestCase { * @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 predicate, boolean expected) { + private void assertEnabled(OperationMode mode, Predicate predicate, boolean expected) { Status status = mock(Status.class); when(status.getMode()).thenReturn(mode); diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java index eae8e7ead53..078ed00af1f 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicenseState.java @@ -5,6 +5,7 @@ */ 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; @@ -23,31 +24,51 @@ 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().isPaid(); + return status.getMode() != OperationMode.BASIC; } /** * Indicates whether the stats and health API calls should be allowed. If a license is expired and past the grace * period then we deny these calls. * - * @return true if the license allows for the stats and health apis to be used. + * @return true if the license allows for the stats and health APIs to be used. */ public boolean statsAndHealthEnabled() { return status.getLicenseState() != LicenseState.DISABLED; } /** - * @return true if the license enables DLS and FLS + * Determine if Document Level Security (DLS) and Field Level Security (FLS) should be enabled. + *

+ * DLS and FLS are only disabled when the mode is not: + *

    + *
  • {@link OperationMode#PLATINUM}
  • + *
  • {@link OperationMode#TRIAL}
  • + *
+ * Note: This does not consider the state of the license so that Security does not suddenly leak information! + * + * @return {@code true} to enable DLS and FLS. Otherwise {@code false}. */ public boolean documentAndFieldLevelSecurityEnabled() { - return status.getMode().allFeaturesEnabled(); + Status status = this.status; + return status.getMode() == OperationMode.TRIAL || status.getMode() == OperationMode.PLATINUM; } /** - * @return true if the license enables the use of custom authentication realms + * Determine if Custom Realms should be enabled. + *

+ * Custom Realms are only disabled when the mode is not: + *

    + *
  • {@link OperationMode#PLATINUM}
  • + *
  • {@link OperationMode#TRIAL}
  • + *
+ * Note: This does not consider the state of the license so that Security does not suddenly block requests! + * + * @return {@code true} to enable Custom Realms. Otherwise {@code false}. */ public boolean customRealmsEnabled() { - return status.getMode().allFeaturesEnabled(); + Status status = this.status; + return status.getMode() == OperationMode.TRIAL || status.getMode() == OperationMode.PLATINUM; } void updateStatus(Status status) { diff --git a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java index 5ee1ff9f165..7befc95f4c6 100644 --- a/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java +++ b/elasticsearch/x-pack/shield/src/main/java/org/elasticsearch/shield/license/ShieldLicensee.java @@ -48,19 +48,31 @@ public class ShieldLicensee extends AbstractLicenseeComponent im public String[] acknowledgmentMessages(License currentLicense, License newLicense) { switch (newLicense.operationMode()) { case BASIC: - 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."}; + 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.", + "Field and document level access control will be disabled", + "Custom realms will be ignored" + }; + } } break; case GOLD: - // 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" - }; + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case BASIC: // though technically it was already disabled, it's not bad to remind them + case TRIAL: + case PLATINUM: + return new String[] { + "Field and document level access control will be disabled", + "Custom realms will be ignored" + }; + } } break; } diff --git a/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseeTests.java b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseeTests.java index 2cfc3aeca45..bf22fea70a1 100644 --- a/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseeTests.java +++ b/elasticsearch/x-pack/shield/src/test/java/org/elasticsearch/shield/license/ShieldLicenseeTests.java @@ -58,23 +58,23 @@ public class ShieldLicenseeTests extends AbstractLicenseeTestCase { verifyNoMoreInteractions(registry, shieldState); } - public void testAcknowledgementMessagesFromFreeToAnyIsNoOp() { - assertEmptyAck(randomFreeMode(), randomFrom(OperationMode.values()), this::buildLicensee); + public void testAcknowledgementMessagesFromBasicToAnyIsNoOp() { + assertEmptyAck(OperationMode.BASIC, randomMode(), this::buildLicensee); } - public void testAcknowledgementMessagesFromAnyToNonGoldPaidIsNoOp() { - assertEmptyAck(randomFrom(OperationMode.values()), randomFromPaidExcept(OperationMode.GOLD), this::buildLicensee); + public void testAcknowledgementMessagesFromAnyToTrialOrPlatinumIsNoOp() { + assertEmptyAck(randomMode(), randomTrialOrPlatinumMode(), this::buildLicensee); } - public void testAcknowledgementMessagesFromPaidToFreeNotesLimits() { - String[] messages = ackLicenseChange(randomPaidMode(), randomFreeMode(), this::buildLicensee); + public void testAcknowledgementMessagesFromTrialGoldOrPlatinumToBasicNotesLimits() { + String[] messages = ackLicenseChange(randomTrialGoldOrPlatinumMode(), OperationMode.BASIC, this::buildLicensee); // leaving messages up to inspection - assertThat(messages.length, equalTo(1)); + assertThat(messages.length, equalTo(3)); } - public void testAcknowledgementMessagesFromNonGoldPaidToGoldNotesLimits() { - String[] messages = ackLicenseChange(randomFromPaidExcept(OperationMode.GOLD), OperationMode.GOLD, this::buildLicensee); + public void testAcknowledgementMessagesFromTrialOrPlatinumToGoldNotesLimits() { + String[] messages = ackLicenseChange(randomTrialOrPlatinumMode(), OperationMode.GOLD, this::buildLicensee); // leaving messages up to inspection assertThat(messages.length, equalTo(2)); diff --git a/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java index a0d72e6054d..2e4569183dc 100644 --- a/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java +++ b/elasticsearch/x-pack/watcher/src/main/java/org/elasticsearch/watcher/license/WatcherLicensee.java @@ -9,11 +9,16 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.common.inject.Inject; 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.AbstractLicenseeComponent; 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.TRIAL; +import static org.elasticsearch.license.core.License.OperationMode.GOLD; +import static org.elasticsearch.license.core.License.OperationMode.PLATINUM; + public class WatcherLicensee extends AbstractLicenseeComponent { public static final String ID = Watcher.NAME; @@ -36,8 +41,13 @@ public class WatcherLicensee extends AbstractLicenseeComponent public String[] acknowledgmentMessages(License currentLicense, License newLicense) { switch (newLicense.operationMode()) { case BASIC: - if (currentLicense != null && currentLicense.operationMode().isPaid()) { - return new String[] { "Watcher will be disabled" }; + if (currentLicense != null) { + switch (currentLicense.operationMode()) { + case TRIAL: + case GOLD: + case PLATINUM: + return new String[] { "Watcher will be disabled" }; + } } break; } @@ -56,10 +66,25 @@ public class WatcherLicensee extends AbstractLicenseeComponent return isWatcherTransportActionAllowed(); } + /** + * Determine if Watcher should be enabled. + *

+ * Watcher is only disabled when the license has expired or if the mode is not: + *

    + *
  • {@link OperationMode#PLATINUM}
  • + *
  • {@link OperationMode#GOLD}
  • + *
  • {@link OperationMode#TRIAL}
  • + *
+ * + * @return {@code true} as long as the license is valid. Otherwise {@code false}. + */ public boolean isWatcherTransportActionAllowed() { // status is volatile, so a local variable is used for a consistent view Status localStatus = status; - return localStatus.getLicenseState().isActive() && localStatus.getMode().isPaid(); + OperationMode operationMode = localStatus.getMode(); + boolean licensed = operationMode == TRIAL || operationMode == GOLD || operationMode == PLATINUM; + + return licensed && localStatus.getLicenseState() != LicenseState.DISABLED; } } diff --git a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java index cddb77515a1..742d8454915 100644 --- a/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java +++ b/elasticsearch/x-pack/watcher/src/test/java/org/elasticsearch/watcher/license/LicenseTests.java @@ -5,15 +5,9 @@ */ 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.core.License.OperationMode; import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase; -import org.elasticsearch.license.plugin.core.Licensee; -import org.elasticsearch.license.plugin.core.LicenseeRegistry; - -import java.util.ArrayList; -import java.util.List; import static org.hamcrest.Matchers.is; @@ -22,7 +16,7 @@ public class LicenseTests extends AbstractLicenseeTestCase { private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry(); public void testPlatinumGoldTrialLicenseCanDoEverything() throws Exception { - licenseeRegistry.setOperationMode(randomPaidMode()); + licenseeRegistry.setOperationMode(randomTrialGoldOrPlatinumMode()); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); @@ -30,7 +24,7 @@ public class LicenseTests extends AbstractLicenseeTestCase { } public void testBasicLicenseIsDisabled() throws Exception { - licenseeRegistry.setOperationMode(randomFreeMode()); + licenseeRegistry.setOperationMode(OperationMode.BASIC); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); @@ -38,7 +32,7 @@ public class LicenseTests extends AbstractLicenseeTestCase { } public void testNoLicenseDoesNotWork() { - licenseeRegistry.setOperationMode(randomFreeMode()); + licenseeRegistry.setOperationMode(OperationMode.BASIC); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); licenseeRegistry.disable(); @@ -47,7 +41,7 @@ public class LicenseTests extends AbstractLicenseeTestCase { } public void testExpiredPlatinumGoldTrialLicenseIsRestricted() throws Exception { - licenseeRegistry.setOperationMode(randomPaidMode()); + licenseeRegistry.setOperationMode(randomTrialGoldOrPlatinumMode()); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); licenseeRegistry.disable(); @@ -56,36 +50,36 @@ public class LicenseTests extends AbstractLicenseeTestCase { } public void testUpgradingFromBasicLicenseWorks() { - licenseeRegistry.setOperationMode(randomFreeMode()); + licenseeRegistry.setOperationMode(OperationMode.BASIC); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); assertLicenseBasicOrNoneOrExpiredBehaviour(watcherLicensee); - licenseeRegistry.setOperationMode(randomPaidMode()); + licenseeRegistry.setOperationMode(randomTrialGoldOrPlatinumMode()); assertLicenseGoldPlatinumTrialBehaviour(watcherLicensee); } public void testDowngradingToBasicLicenseWorks() { - licenseeRegistry.setOperationMode(randomPaidMode()); + licenseeRegistry.setOperationMode(randomTrialGoldOrPlatinumMode()); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); assertLicenseGoldPlatinumTrialBehaviour(watcherLicensee); - licenseeRegistry.setOperationMode(randomFreeMode()); + licenseeRegistry.setOperationMode(OperationMode.BASIC); assertLicenseBasicOrNoneOrExpiredBehaviour(watcherLicensee); } public void testUpgradingExpiredLicenseWorks() { - licenseeRegistry.setOperationMode(randomPaidMode()); + licenseeRegistry.setOperationMode(randomTrialGoldOrPlatinumMode()); WatcherLicensee watcherLicensee = new WatcherLicensee(Settings.EMPTY, licenseeRegistry); licenseeRegistry.register(watcherLicensee); licenseeRegistry.disable(); assertLicenseBasicOrNoneOrExpiredBehaviour(watcherLicensee); - licenseeRegistry.setOperationMode(randomPaidMode()); + licenseeRegistry.setOperationMode(randomTrialGoldOrPlatinumMode()); assertLicenseGoldPlatinumTrialBehaviour(watcherLicensee); } @@ -102,36 +96,4 @@ public class LicenseTests extends AbstractLicenseeTestCase { assertThat("Expected watcher transport actions not to be allowed", watcherLicensee.isWatcherTransportActionAllowed(), is(false)); assertThat("Expected actions of a watch not to be executed", watcherLicensee.isExecutingActionsAllowed(), is(false)); } - - public static class SimpleLicenseeRegistry extends AbstractComponent implements LicenseeRegistry { - private final List licensees = new ArrayList<>(); - private License.OperationMode operationMode; - - public SimpleLicenseeRegistry() { - super(Settings.EMPTY); - } - - @Override - public void register(Licensee licensee) { - licensees.add(licensee); - enable(); - } - - public void enable() { - for (Licensee licensee : licensees) { - licensee.onChange(new Licensee.Status(operationMode, randomActiveState())); - } - } - - public void disable() { - for (Licensee licensee : licensees) { - licensee.onChange(new Licensee.Status(operationMode, randomInactiveState())); - } - } - - public void setOperationMode(License.OperationMode operationMode) { - this.operationMode = operationMode; - enable(); - } - } }