Make LicensesService tests more robust
- split out LicensesManagerService & LicensesClientService tests - add removeLicenses tests - other refactoring Original commit: elastic/x-pack-elasticsearch@a47dc586d7
This commit is contained in:
parent
42d47a1bcc
commit
8e9574a925
2
pom.xml
2
pom.xml
|
@ -15,7 +15,7 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<elasticsearch.version>1.4.0-SNAPSHOT</elasticsearch.version>
|
<elasticsearch.version>1.4.0</elasticsearch.version>
|
||||||
<lucene.version>4.10.2</lucene.version>
|
<lucene.version>4.10.2</lucene.version>
|
||||||
<!-- TODO: do we want to always enforce non-default keys -->
|
<!-- TODO: do we want to always enforce non-default keys -->
|
||||||
<keys.path>${basedir}/src/test/resources</keys.path>
|
<keys.path>${basedir}/src/test/resources</keys.path>
|
||||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Set;
|
||||||
|
|
||||||
public class ESLicenseSigner {
|
public class ESLicenseSigner {
|
||||||
|
|
||||||
public static String DEFAULT_PASS_PHRASE = "elasticsearch-license";
|
public final static String DEFAULT_PASS_PHRASE = "elasticsearch-license";
|
||||||
|
|
||||||
private final static int VERSION_START = 0;
|
private final static int VERSION_START = 0;
|
||||||
private final static int VERSION = VERSION_START;
|
private final static int VERSION = VERSION_START;
|
||||||
|
|
|
@ -43,7 +43,7 @@ public class KeyPairGeneratorTool extends CliTool {
|
||||||
|
|
||||||
private static class KeyPairGenerator extends Command {
|
private static class KeyPairGenerator extends Command {
|
||||||
|
|
||||||
public static String DEFAULT_PASS_PHRASE = "elasticsearch-license";
|
public static final String DEFAULT_PASS_PHRASE = "elasticsearch-license";
|
||||||
private static final String NAME = "key-pair-generator";
|
private static final String NAME = "key-pair-generator";
|
||||||
private static final CliToolConfig.Cmd CMD = cmd(NAME, KeyPairGenerator.class)
|
private static final CliToolConfig.Cmd CMD = cmd(NAME, KeyPairGenerator.class)
|
||||||
.options(
|
.options(
|
||||||
|
|
|
@ -76,9 +76,9 @@ public class LicenseGeneratorTool extends CliTool {
|
||||||
String[] licenseSpecSources = commandLine.getOptionValues("license");
|
String[] licenseSpecSources = commandLine.getOptionValues("license");
|
||||||
String[] licenseSpecSourceFiles = commandLine.getOptionValues("licenseFile");
|
String[] licenseSpecSourceFiles = commandLine.getOptionValues("licenseFile");
|
||||||
|
|
||||||
if (!exists(privateKeyPath)) {
|
if (doesNotExist(privateKeyPath)) {
|
||||||
return exitCmd(ExitStatus.USAGE, terminal, privateKeyPath + " does not exist");
|
return exitCmd(ExitStatus.USAGE, terminal, privateKeyPath + " does not exist");
|
||||||
} else if (!exists(publicKeyPath)) {
|
} else if (doesNotExist(publicKeyPath)) {
|
||||||
return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " does not exist");
|
return exitCmd(ExitStatus.USAGE, terminal, publicKeyPath + " does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ public class LicenseGeneratorTool extends CliTool {
|
||||||
if (licenseSpecSourceFiles != null) {
|
if (licenseSpecSourceFiles != null) {
|
||||||
for (String licenseSpecFilePath : licenseSpecSourceFiles) {
|
for (String licenseSpecFilePath : licenseSpecSourceFiles) {
|
||||||
Path licenseSpecPath = Paths.get(licenseSpecFilePath);
|
Path licenseSpecPath = Paths.get(licenseSpecFilePath);
|
||||||
if (!exists(licenseSpecFilePath)) {
|
if (doesNotExist(licenseSpecFilePath)) {
|
||||||
return exitCmd(ExitStatus.USAGE, terminal, licenseSpecFilePath + " does not exist");
|
return exitCmd(ExitStatus.USAGE, terminal, licenseSpecFilePath + " does not exist");
|
||||||
}
|
}
|
||||||
licenseSpecs.addAll(ESLicenses.fromSource(Files.readAllBytes(licenseSpecPath), false));
|
licenseSpecs.addAll(ESLicenses.fromSource(Files.readAllBytes(licenseSpecPath), false));
|
||||||
|
@ -122,8 +122,8 @@ public class LicenseGeneratorTool extends CliTool {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static boolean exists(String filePath) {
|
private static boolean doesNotExist(String filePath) {
|
||||||
return new File(filePath).exists();
|
return !new File(filePath).exists();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -169,7 +169,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class LicensesUpdateResponse extends ClusterStateUpdateResponse {
|
public static class LicensesUpdateResponse extends ClusterStateUpdateResponse {
|
||||||
private LicensesStatus status;
|
private final LicensesStatus status;
|
||||||
|
|
||||||
public LicensesUpdateResponse(boolean acknowledged, LicensesStatus status) {
|
public LicensesUpdateResponse(boolean acknowledged, LicensesStatus status) {
|
||||||
super(acknowledged);
|
super(acknowledged);
|
||||||
|
|
|
@ -12,7 +12,7 @@ public enum LicensesStatus {
|
||||||
INVALID((byte) 1),
|
INVALID((byte) 1),
|
||||||
EXPIRED((byte) 2);
|
EXPIRED((byte) 2);
|
||||||
|
|
||||||
private byte id;
|
private final byte id;
|
||||||
|
|
||||||
LicensesStatus(byte id) {
|
LicensesStatus(byte id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
|
@ -30,6 +30,7 @@ import static org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.Comm
|
||||||
import static org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.LicenseGenerator;
|
import static org.elasticsearch.license.licensor.tools.LicenseGeneratorTool.LicenseGenerator;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
import static org.hamcrest.core.IsEqual.equalTo;
|
import static org.hamcrest.core.IsEqual.equalTo;
|
||||||
|
|
||||||
public class LicenseGenerationToolTests extends CliToolTestCase {
|
public class LicenseGenerationToolTests extends CliToolTestCase {
|
||||||
|
@ -134,13 +135,14 @@ public class LicenseGenerationToolTests extends CliToolTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void testParsingMultipleLicense() throws Exception {
|
public void testParsingMultipleLicense() throws Exception {
|
||||||
int n = randomIntBetween(2, 5);
|
int n = randomIntBetween(2, 5);
|
||||||
List<LicenseSpec> inputLicenseSpecs = new ArrayList<>();
|
Map<String, LicenseSpec> inputLicenseSpecs = new HashMap<>();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
inputLicenseSpecs.add(generateRandomLicenseSpec());
|
LicenseSpec licenseSpec = generateRandomLicenseSpec();
|
||||||
|
inputLicenseSpecs.put(licenseSpec.feature, licenseSpec);
|
||||||
}
|
}
|
||||||
LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool();
|
LicenseGeneratorTool licenseGeneratorTool = new LicenseGeneratorTool();
|
||||||
Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME,
|
Command command = licenseGeneratorTool.parse(LicenseGeneratorTool.NAME,
|
||||||
args("--license " + generateESLicenseSpecString(inputLicenseSpecs)
|
args("--license " + generateESLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values()))
|
||||||
+ " --publicKeyPath " + pubKeyPath
|
+ " --publicKeyPath " + pubKeyPath
|
||||||
+ " --privateKeyPath " + priKeyPath));
|
+ " --privateKeyPath " + priKeyPath));
|
||||||
|
|
||||||
|
@ -148,44 +150,33 @@ public class LicenseGenerationToolTests extends CliToolTestCase {
|
||||||
LicenseGenerator licenseGenerator = (LicenseGenerator) command;
|
LicenseGenerator licenseGenerator = (LicenseGenerator) command;
|
||||||
assertThat(licenseGenerator.publicKeyFilePath, equalTo(pubKeyPath));
|
assertThat(licenseGenerator.publicKeyFilePath, equalTo(pubKeyPath));
|
||||||
assertThat(licenseGenerator.privateKeyFilePath, equalTo(priKeyPath));
|
assertThat(licenseGenerator.privateKeyFilePath, equalTo(priKeyPath));
|
||||||
assertThat(licenseGenerator.licenseSpecs.size(), equalTo(n));
|
assertThat(licenseGenerator.licenseSpecs.size(), equalTo(inputLicenseSpecs.size()));
|
||||||
|
|
||||||
for (LicenseSpec inputSpec : inputLicenseSpecs) {
|
for (ESLicense outputLicenseSpec : licenseGenerator.licenseSpecs) {
|
||||||
boolean found = false;
|
LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicenseSpec.feature());
|
||||||
for (ESLicense outputSpec : licenseGenerator.licenseSpecs) {
|
assertThat(inputLicenseSpec, notNullValue());
|
||||||
if (inputSpec.uid.equals(outputSpec.uid())) {
|
assertLicenseSpec(inputLicenseSpec, outputLicenseSpec);
|
||||||
assertLicenseSpec(inputSpec, outputSpec);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertThat(found, equalTo(true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTool() throws Exception {
|
public void testTool() throws Exception {
|
||||||
int n = randomIntBetween(1, 5);
|
int n = randomIntBetween(1, 5);
|
||||||
List<LicenseSpec> inputLicenseSpecs = new ArrayList<>();
|
Map<String, LicenseSpec> inputLicenseSpecs = new HashMap<>();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
inputLicenseSpecs.add(generateRandomLicenseSpec());
|
LicenseSpec licenseSpec = generateRandomLicenseSpec();
|
||||||
|
inputLicenseSpecs.put(licenseSpec.feature, licenseSpec);
|
||||||
}
|
}
|
||||||
List<ESLicense> licenseSpecs = ESLicenses.fromSource(generateESLicenseSpecString(inputLicenseSpecs).getBytes(StandardCharsets.UTF_8), false);
|
List<ESLicense> licenseSpecs = ESLicenses.fromSource(generateESLicenseSpecString(new ArrayList<>(inputLicenseSpecs.values())).getBytes(StandardCharsets.UTF_8), false);
|
||||||
|
|
||||||
String output = runLicenseGenerationTool(pubKeyPath, priKeyPath, new HashSet<>(licenseSpecs), ExitStatus.OK);
|
String output = runLicenseGenerationTool(pubKeyPath, priKeyPath, new HashSet<>(licenseSpecs), ExitStatus.OK);
|
||||||
List<ESLicense> outputLicenses = ESLicenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true);
|
List<ESLicense> outputLicenses = ESLicenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true);
|
||||||
assertThat(outputLicenses.size(), equalTo(n));
|
assertThat(outputLicenses.size(), equalTo(inputLicenseSpecs.size()));
|
||||||
|
|
||||||
for (LicenseSpec inputSpec : inputLicenseSpecs) {
|
for (ESLicense outputLicense : outputLicenses) {
|
||||||
boolean found = false;
|
LicenseSpec inputLicenseSpec = inputLicenseSpecs.get(outputLicense.feature());
|
||||||
for (ESLicense license : outputLicenses) {
|
assertThat(inputLicenseSpec, notNullValue());
|
||||||
if (inputSpec.uid.equals(license.uid())) {
|
assertLicenseSpec(inputLicenseSpec, outputLicense);
|
||||||
assertLicenseSpec(inputSpec, license);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertThat(found, equalTo(true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,16 +25,14 @@ import org.junit.rules.TemporaryFolder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import static org.elasticsearch.common.cli.CliTool.Command;
|
import static org.elasticsearch.common.cli.CliTool.Command;
|
||||||
import static org.elasticsearch.common.cli.CliTool.ExitStatus;
|
import static org.elasticsearch.common.cli.CliTool.ExitStatus;
|
||||||
import static org.elasticsearch.license.AbstractLicensingTestBase.generateSignedLicense;
|
import static org.elasticsearch.license.AbstractLicensingTestBase.generateSignedLicense;
|
||||||
import static org.elasticsearch.license.licensor.tools.LicenseVerificationTool.LicenseVerifier;
|
import static org.elasticsearch.license.licensor.tools.LicenseVerificationTool.LicenseVerifier;
|
||||||
import static org.hamcrest.CoreMatchers.instanceOf;
|
import static org.hamcrest.CoreMatchers.instanceOf;
|
||||||
|
import static org.hamcrest.CoreMatchers.notNullValue;
|
||||||
import static org.hamcrest.core.IsEqual.equalTo;
|
import static org.hamcrest.core.IsEqual.equalTo;
|
||||||
|
|
||||||
public class LicenseVerificationToolTests extends CliToolTestCase {
|
public class LicenseVerificationToolTests extends CliToolTestCase {
|
||||||
|
@ -85,14 +83,15 @@ public class LicenseVerificationToolTests extends CliToolTestCase {
|
||||||
@Test
|
@Test
|
||||||
public void testParsingMultipleLicense() throws Exception {
|
public void testParsingMultipleLicense() throws Exception {
|
||||||
int n = randomIntBetween(2, 5);
|
int n = randomIntBetween(2, 5);
|
||||||
Set<ESLicense> inputLicenses = new HashSet<>();
|
Map<String, ESLicense> inputLicenses = new HashMap<>();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
inputLicenses.add(generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
|
ESLicense esLicense = generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
|
||||||
TimeValue.timeValueHours(1)));
|
TimeValue.timeValueHours(1));
|
||||||
|
inputLicenses.put(esLicense.feature(), esLicense);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringBuilder argsBuilder = new StringBuilder();
|
StringBuilder argsBuilder = new StringBuilder();
|
||||||
for (ESLicense inputLicense : inputLicenses) {
|
for (ESLicense inputLicense : inputLicenses.values()) {
|
||||||
argsBuilder.append(" --license ")
|
argsBuilder.append(" --license ")
|
||||||
.append(dumpLicense(inputLicense));
|
.append(dumpLicense(inputLicense));
|
||||||
}
|
}
|
||||||
|
@ -101,44 +100,33 @@ public class LicenseVerificationToolTests extends CliToolTestCase {
|
||||||
|
|
||||||
assertThat(command, instanceOf(LicenseVerifier.class));
|
assertThat(command, instanceOf(LicenseVerifier.class));
|
||||||
LicenseVerifier licenseVerifier = (LicenseVerifier) command;
|
LicenseVerifier licenseVerifier = (LicenseVerifier) command;
|
||||||
assertThat(licenseVerifier.licenses.size(), equalTo(n));
|
assertThat(licenseVerifier.licenses.size(), equalTo(inputLicenses.size()));
|
||||||
|
|
||||||
for (ESLicense inputLicense : inputLicenses) {
|
for (ESLicense outputLicense : licenseVerifier.licenses) {
|
||||||
boolean found = false;
|
ESLicense inputLicense = inputLicenses.get(outputLicense.feature());
|
||||||
for (ESLicense outputLicense : licenseVerifier.licenses) {
|
assertThat(inputLicense, notNullValue());
|
||||||
if (inputLicense.uid().equals(outputLicense.uid())) {
|
TestUtils.isSame(inputLicense, outputLicense);
|
||||||
TestUtils.isSame(inputLicense, outputLicense);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertThat(found, equalTo(true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testToolSimple() throws Exception {
|
public void testToolSimple() throws Exception {
|
||||||
int n = randomIntBetween(2, 5);
|
int n = randomIntBetween(2, 5);
|
||||||
Set<ESLicense> inputLicenses = new HashSet<>();
|
Map<String, ESLicense> inputLicenses = new HashMap<>();
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
inputLicenses.add(generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
|
ESLicense esLicense = generateSignedLicense(randomRealisticUnicodeOfCodepointLengthBetween(5, 15),
|
||||||
TimeValue.timeValueHours(1)));
|
TimeValue.timeValueHours(1));
|
||||||
|
inputLicenses.put(esLicense.feature(), esLicense);
|
||||||
}
|
}
|
||||||
|
|
||||||
String output = runLicenseVerificationTool(inputLicenses, ExitStatus.OK);
|
String output = runLicenseVerificationTool(new HashSet<>(inputLicenses.values()), ExitStatus.OK);
|
||||||
List<ESLicense> outputLicenses = ESLicenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true);
|
List<ESLicense> outputLicenses = ESLicenses.fromSource(output.getBytes(StandardCharsets.UTF_8), true);
|
||||||
assertThat(outputLicenses.size(), equalTo(n));
|
assertThat(outputLicenses.size(), equalTo(inputLicenses.size()));
|
||||||
|
|
||||||
for (ESLicense inputLicense : inputLicenses) {
|
for (ESLicense outputLicense : outputLicenses) {
|
||||||
boolean found = false;
|
ESLicense inputLicense = inputLicenses.get(outputLicense.feature());
|
||||||
for (ESLicense outputLicense : outputLicenses) {
|
assertThat(inputLicense, notNullValue());
|
||||||
if (inputLicense.uid().equals(outputLicense.uid())) {
|
TestUtils.isSame(inputLicense, outputLicense);
|
||||||
TestUtils.isSame(inputLicense, outputLicense);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertThat(found, equalTo(true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.license.plugin;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.cluster.ClusterChangedEvent;
|
||||||
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
|
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||||
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.license.core.ESLicense;
|
||||||
|
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||||
|
import org.elasticsearch.license.plugin.core.LicensesClientService;
|
||||||
|
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||||
|
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||||
|
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||||
|
import org.elasticsearch.test.InternalTestCluster;
|
||||||
|
import org.junit.Before;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static org.elasticsearch.license.plugin.core.LicensesService.LicensesUpdateResponse;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
public class AbstractLicensesServiceTests extends AbstractLicensesIntegrationTests {
|
||||||
|
|
||||||
|
private static String node = null;
|
||||||
|
private static String[] nodes;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void beforeTest() throws Exception {
|
||||||
|
wipeAllLicenses();
|
||||||
|
|
||||||
|
DiscoveryNodes discoveryNodes = masterClusterService().state().getNodes();
|
||||||
|
Set<String> dataNodeSet = new HashSet<>();
|
||||||
|
for (DiscoveryNode discoveryNode : discoveryNodes) {
|
||||||
|
if (discoveryNode.dataNode()) {
|
||||||
|
dataNodeSet.add(discoveryNode.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes = dataNodeSet.toArray(new String[dataNodeSet.size()]);
|
||||||
|
node = nodes[randomIntBetween(0, nodes.length - 1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void registerAndAckSignedLicenses(final LicensesManagerService masterLicensesManagerService, final List<ESLicense> license, final LicensesStatus expectedStatus) {
|
||||||
|
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().licenses(license);
|
||||||
|
LicensesService.PutLicenseRequestHolder requestHolder = new LicensesService.PutLicenseRequestHolder(putLicenseRequest, "test");
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
final AtomicBoolean success = new AtomicBoolean(false);
|
||||||
|
masterLicensesManagerService.registerLicenses(requestHolder, new ActionListener<LicensesUpdateResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(LicensesUpdateResponse licensesUpdateResponse) {
|
||||||
|
if (licensesUpdateResponse.isAcknowledged() && licensesUpdateResponse.status() == expectedStatus) {
|
||||||
|
success.set(true);
|
||||||
|
}
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable e) {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
assertThat("register license(s) failed", success.get(), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Action registerWithTrialLicense(final LicensesClientService clientService, final LicensesClientService.Listener clientListener, final String feature, final TimeValue expiryDuration) {
|
||||||
|
return new Action(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
clientService.register(feature, new LicensesService.TrialLicenseOptions(expiryDuration, 10),
|
||||||
|
clientListener);
|
||||||
|
|
||||||
|
// invoke clusterChanged event to flush out pendingRegistration
|
||||||
|
LicensesService licensesService = (LicensesService) clientService;
|
||||||
|
ClusterChangedEvent event = new ClusterChangedEvent("", clusterService().state(), clusterService().state());
|
||||||
|
licensesService.clusterChanged(event);
|
||||||
|
}
|
||||||
|
}, 0, 1, "should trigger onEnable for " + feature + " once [trial license]");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class TestTrackingClientListener implements LicensesClientService.Listener {
|
||||||
|
CountDownLatch enableLatch;
|
||||||
|
CountDownLatch disableLatch;
|
||||||
|
|
||||||
|
final boolean track;
|
||||||
|
|
||||||
|
public TestTrackingClientListener(boolean track) {
|
||||||
|
this.track = track;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestTrackingClientListener() {
|
||||||
|
this(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void latch(CountDownLatch enableLatch, CountDownLatch disableLatch) {
|
||||||
|
this.enableLatch = enableLatch;
|
||||||
|
this.disableLatch = disableLatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onEnabled() {
|
||||||
|
if (track) {
|
||||||
|
this.enableLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDisabled() {
|
||||||
|
if (track) {
|
||||||
|
this.disableLatch.countDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected class Action {
|
||||||
|
final int expectedDisabledCount;
|
||||||
|
final int expectedEnabledCount;
|
||||||
|
final TimeValue timeout;
|
||||||
|
final Runnable action;
|
||||||
|
final String msg;
|
||||||
|
|
||||||
|
protected Action(Runnable action, int expectedEnabledCount, int expectedDisabledCount, String msg) {
|
||||||
|
this(action, expectedEnabledCount, expectedDisabledCount, TimeValue.timeValueSeconds(1), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Action(Runnable action, int expectedDisabledCount, int expectedEnabledCount, TimeValue timeout, String msg) {
|
||||||
|
this.expectedDisabledCount = expectedDisabledCount;
|
||||||
|
this.expectedEnabledCount = expectedEnabledCount;
|
||||||
|
this.action = action;
|
||||||
|
this.timeout = timeout;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected LicensesManagerService masterLicensesManagerService() {
|
||||||
|
final InternalTestCluster clients = internalCluster();
|
||||||
|
return clients.getInstance(LicensesManagerService.class, clients.getMasterName());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LicensesClientService licensesClientService() {
|
||||||
|
return internalCluster().getInstance(LicensesClientService.class, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected LicensesService randomLicensesService() {
|
||||||
|
String randomNode = randomFrom(nodes);
|
||||||
|
return internalCluster().getInstance(LicensesService.class, randomNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static ClusterService masterClusterService() {
|
||||||
|
final InternalTestCluster clients = internalCluster();
|
||||||
|
return clients.getInstance(ClusterService.class, clients.getMasterName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,98 +5,26 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.license.plugin;
|
package org.elasticsearch.license.plugin;
|
||||||
|
|
||||||
import org.elasticsearch.action.ActionListener;
|
|
||||||
import org.elasticsearch.cluster.ClusterChangedEvent;
|
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
|
||||||
import org.elasticsearch.common.collect.ImmutableSet;
|
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.license.TestUtils;
|
|
||||||
import org.elasticsearch.license.core.ESLicense;
|
import org.elasticsearch.license.core.ESLicense;
|
||||||
import org.elasticsearch.license.manager.ESLicenseManager;
|
import org.elasticsearch.license.plugin.core.LicensesClientService;
|
||||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||||
import org.elasticsearch.license.plugin.core.*;
|
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||||
import org.elasticsearch.test.InternalTestCluster;
|
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import static org.elasticsearch.license.plugin.core.LicensesService.LicensesUpdateResponse;
|
|
||||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||||
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
@ClusterScope(scope = TEST, numDataNodes = 10)
|
@ClusterScope(scope = TEST, numDataNodes = 10)
|
||||||
public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
public class LicensesClientServiceTests extends AbstractLicensesServiceTests {
|
||||||
|
|
||||||
private static String node = null;
|
|
||||||
private static String[] nodes;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void beforeTest() throws Exception {
|
|
||||||
wipeAllLicenses();
|
|
||||||
|
|
||||||
DiscoveryNodes discoveryNodes = LicensesServiceTests.masterClusterService().state().getNodes();
|
|
||||||
Set<String> dataNodeSet = new HashSet<>();
|
|
||||||
for (DiscoveryNode discoveryNode : discoveryNodes) {
|
|
||||||
if (discoveryNode.dataNode()) {
|
|
||||||
dataNodeSet.add(discoveryNode.getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodes = dataNodeSet.toArray(new String[dataNodeSet.size()]);
|
|
||||||
node = nodes[randomIntBetween(0, nodes.length - 1)];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testStoreAndGetLicenses() throws Exception {
|
|
||||||
LicensesManagerService licensesManagerService = masterLicensesManagerService();
|
|
||||||
ESLicense shieldShortLicense = generateSignedLicense("shield", TimeValue.timeValueHours(1));
|
|
||||||
ESLicense shieldLongLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2));
|
|
||||||
ESLicense marvelShortLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(1));
|
|
||||||
ESLicense marvelLongLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2));
|
|
||||||
|
|
||||||
List<ESLicense> licenses = Arrays.asList(shieldLongLicense, shieldShortLicense, marvelLongLicense, marvelShortLicense);
|
|
||||||
Collections.shuffle(licenses);
|
|
||||||
putAndCheckSignedLicensesAction(licensesManagerService, licenses, LicensesStatus.VALID);
|
|
||||||
|
|
||||||
final ImmutableSet<String> licenseSignatures = masterLicenseManager().toSignatures(licenses);
|
|
||||||
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
|
||||||
|
|
||||||
// all licenses should be stored in the metaData
|
|
||||||
assertThat(licenseSignatures, equalTo(licensesMetaData.getSignatures()));
|
|
||||||
|
|
||||||
// only the latest expiry date license for each feature should be returned by getLicenses()
|
|
||||||
final List<ESLicense> getLicenses = licensesManagerService.getLicenses();
|
|
||||||
TestUtils.isSame(getLicenses, Arrays.asList(shieldLongLicense, marvelLongLicense));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInvalidLicenseStorage() throws Exception {
|
|
||||||
LicensesManagerService licensesManagerService = masterLicensesManagerService();
|
|
||||||
ESLicense signedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
|
|
||||||
|
|
||||||
// modify content of signed license
|
|
||||||
ESLicense tamperedLicense = ESLicense.builder()
|
|
||||||
.fromLicenseSpec(signedLicense, signedLicense.signature())
|
|
||||||
.expiryDate(signedLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l)
|
|
||||||
.verify()
|
|
||||||
.build();
|
|
||||||
|
|
||||||
putAndCheckSignedLicensesAction(licensesManagerService, Arrays.asList(tamperedLicense), LicensesStatus.INVALID);
|
|
||||||
|
|
||||||
// ensure that the invalid license never made it to cluster state
|
|
||||||
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
|
||||||
if (licensesMetaData != null) {
|
|
||||||
assertThat(licensesMetaData.getSignatures().size(), equalTo(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTrialLicenseEnforcement() throws Exception {
|
public void testTrialLicenseEnforcement() throws Exception {
|
||||||
|
@ -260,33 +188,6 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void putAndCheckSignedLicensesAction(final LicensesManagerService masterLicensesManagerService, final List<ESLicense> license, final LicensesStatus expectedStatus) {
|
|
||||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest().licenses(license);
|
|
||||||
LicensesService.PutLicenseRequestHolder requestHolder = new LicensesService.PutLicenseRequestHolder(putLicenseRequest, "test");
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
final AtomicBoolean success = new AtomicBoolean(false);
|
|
||||||
masterLicensesManagerService.registerLicenses(requestHolder, new ActionListener<LicensesUpdateResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(LicensesUpdateResponse licensesUpdateResponse) {
|
|
||||||
if (licensesUpdateResponse.isAcknowledged() && licensesUpdateResponse.status() == expectedStatus) {
|
|
||||||
success.set(true);
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(Throwable e) {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
fail(e.getMessage());
|
|
||||||
}
|
|
||||||
assertThat(success.get(), equalTo(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Action generateAndPutSignedLicenseAction(final LicensesManagerService masterLicensesManagerService, final String feature, final TimeValue expiryDuration) throws Exception {
|
private Action generateAndPutSignedLicenseAction(final LicensesManagerService masterLicensesManagerService, final String feature, final TimeValue expiryDuration) throws Exception {
|
||||||
return new Action(new Runnable() {
|
return new Action(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -298,7 +199,7 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
||||||
fail(e.getMessage());
|
fail(e.getMessage());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
putAndCheckSignedLicensesAction(masterLicensesManagerService, Arrays.asList(license), LicensesStatus.VALID);
|
registerAndAckSignedLicenses(masterLicensesManagerService, Arrays.asList(license), LicensesStatus.VALID);
|
||||||
}
|
}
|
||||||
}, 0, 1, "should trigger onEnable for " + feature + " once [signed license]");
|
}, 0, 1, "should trigger onEnable for " + feature + " once [signed license]");
|
||||||
}
|
}
|
||||||
|
@ -312,21 +213,6 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
||||||
}, 0, 0, "should not trigger any notification [disabled by default]");
|
}, 0, 0, "should not trigger any notification [disabled by default]");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Action registerWithTrialLicense(final LicensesClientService clientService, final LicensesClientService.Listener clientListener, final String feature, final TimeValue expiryDuration) {
|
|
||||||
return new Action(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
clientService.register(feature, new LicensesService.TrialLicenseOptions(expiryDuration, 10),
|
|
||||||
clientListener);
|
|
||||||
|
|
||||||
// invoke clusterChanged event to flush out pendingRegistration
|
|
||||||
LicensesService licensesService = (LicensesService) clientService;
|
|
||||||
ClusterChangedEvent event = new ClusterChangedEvent("", clusterService().state(), clusterService().state());
|
|
||||||
licensesService.clusterChanged(event);
|
|
||||||
}
|
|
||||||
}, 0, 1, "should trigger onEnable for " + feature + " once [trial license]");
|
|
||||||
}
|
|
||||||
|
|
||||||
private Action assertExpiryAction(String feature, String licenseType, TimeValue expiryDuration) {
|
private Action assertExpiryAction(String feature, String licenseType, TimeValue expiryDuration) {
|
||||||
return new Action(new Runnable() {
|
return new Action(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -349,7 +235,7 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
||||||
final CountDownLatch disableLatch = new CountDownLatch(expectedDisableCount.get());
|
final CountDownLatch disableLatch = new CountDownLatch(expectedDisableCount.get());
|
||||||
final AtomicLong cumulativeTimeoutMillis = new AtomicLong(0);
|
final AtomicLong cumulativeTimeoutMillis = new AtomicLong(0);
|
||||||
clientListener.latch(enableLatch, disableLatch);
|
clientListener.latch(enableLatch, disableLatch);
|
||||||
for (final Action action : actions) {
|
for (final Action action : actions) {
|
||||||
action.run();
|
action.run();
|
||||||
cumulativeTimeoutMillis.addAndGet(action.timeout.getMillis());
|
cumulativeTimeoutMillis.addAndGet(action.timeout.getMillis());
|
||||||
}
|
}
|
||||||
|
@ -362,83 +248,14 @@ public class LicensesServiceTests extends AbstractLicensesIntegrationTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getActionMsg(final boolean enabledCount,final long latchCount,final List<Action> actions) {
|
private static String getActionMsg(final boolean enabledCount, final long latchCount, final List<Action> actions) {
|
||||||
AtomicLong cumulativeCount = new AtomicLong(0);
|
AtomicLong cumulativeCount = new AtomicLong(0);
|
||||||
for (Action action : actions) {
|
for (Action action : actions) {
|
||||||
cumulativeCount.addAndGet((enabledCount)? action.expectedEnabledCount : action.expectedDisabledCount);
|
cumulativeCount.addAndGet((enabledCount) ? action.expectedEnabledCount : action.expectedDisabledCount);
|
||||||
if (latchCount <= cumulativeCount.get()) {
|
if (latchCount <= cumulativeCount.get()) {
|
||||||
return action.msg;
|
return action.msg;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return "there should be no errors";
|
return "there should be no errors";
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestTrackingClientListener implements LicensesClientService.Listener {
|
|
||||||
CountDownLatch enableLatch;
|
|
||||||
CountDownLatch disableLatch;
|
|
||||||
|
|
||||||
public synchronized void latch(CountDownLatch enableLatch, CountDownLatch disableLatch) {
|
|
||||||
this.enableLatch = enableLatch;
|
|
||||||
this.disableLatch = disableLatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEnabled() {
|
|
||||||
this.enableLatch.countDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDisabled() {
|
|
||||||
this.disableLatch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class Action {
|
|
||||||
final int expectedDisabledCount;
|
|
||||||
final int expectedEnabledCount;
|
|
||||||
final TimeValue timeout;
|
|
||||||
final Runnable action;
|
|
||||||
final String msg;
|
|
||||||
|
|
||||||
private Action(Runnable action, int expectedEnabledCount, int expectedDisabledCount, String msg) {
|
|
||||||
this(action, expectedEnabledCount, expectedDisabledCount, TimeValue.timeValueSeconds(1), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Action(Runnable action, int expectedDisabledCount, int expectedEnabledCount, TimeValue timeout, String msg) {
|
|
||||||
this.expectedDisabledCount = expectedDisabledCount;
|
|
||||||
this.expectedEnabledCount = expectedEnabledCount;
|
|
||||||
this.action = action;
|
|
||||||
this.timeout = timeout;
|
|
||||||
this.msg = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void run() {
|
|
||||||
action.run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private LicensesManagerService masterLicensesManagerService() {
|
|
||||||
final InternalTestCluster clients = internalCluster();
|
|
||||||
return clients.getInstance(LicensesManagerService.class, clients.getMasterName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private ESLicenseManager masterLicenseManager() {
|
|
||||||
final InternalTestCluster clients = internalCluster();
|
|
||||||
return clients.getInstance(ESLicenseManager.class, clients.getMasterName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private LicensesClientService licensesClientService() {
|
|
||||||
return internalCluster().getInstance(LicensesClientService.class, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
private LicensesService randomLicensesService() {
|
|
||||||
String randomNode = randomFrom(nodes);
|
|
||||||
return internalCluster().getInstance(LicensesService.class, randomNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ClusterService masterClusterService() {
|
|
||||||
final InternalTestCluster clients = internalCluster();
|
|
||||||
return clients.getInstance(ClusterService.class, clients.getMasterName());
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,146 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.license.plugin;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
||||||
|
import org.elasticsearch.common.collect.ImmutableSet;
|
||||||
|
import org.elasticsearch.common.collect.Sets;
|
||||||
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.license.TestUtils;
|
||||||
|
import org.elasticsearch.license.core.ESLicense;
|
||||||
|
import org.elasticsearch.license.manager.ESLicenseManager;
|
||||||
|
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||||
|
import org.elasticsearch.license.plugin.core.*;
|
||||||
|
import org.elasticsearch.test.InternalTestCluster;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||||
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.TEST;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
@ClusterScope(scope = TEST, numDataNodes = 10)
|
||||||
|
public class LicensesManagerServiceTests extends AbstractLicensesServiceTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testStoreAndGetLicenses() throws Exception {
|
||||||
|
LicensesManagerService licensesManagerService = masterLicensesManagerService();
|
||||||
|
ESLicense shieldShortLicense = generateSignedLicense("shield", TimeValue.timeValueHours(1));
|
||||||
|
ESLicense shieldLongLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2));
|
||||||
|
ESLicense marvelShortLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(1));
|
||||||
|
ESLicense marvelLongLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2));
|
||||||
|
|
||||||
|
List<ESLicense> licenses = Arrays.asList(shieldLongLicense, shieldShortLicense, marvelLongLicense, marvelShortLicense);
|
||||||
|
Collections.shuffle(licenses);
|
||||||
|
registerAndAckSignedLicenses(licensesManagerService, licenses, LicensesStatus.VALID);
|
||||||
|
|
||||||
|
final ImmutableSet<String> licenseSignatures = masterLicenseManager().toSignatures(licenses);
|
||||||
|
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
||||||
|
|
||||||
|
// all licenses should be stored in the metaData
|
||||||
|
assertThat(licenseSignatures, equalTo(licensesMetaData.getSignatures()));
|
||||||
|
|
||||||
|
// only the latest expiry date license for each feature should be returned by getLicenses()
|
||||||
|
final List<ESLicense> getLicenses = licensesManagerService.getLicenses();
|
||||||
|
TestUtils.isSame(getLicenses, Arrays.asList(shieldLongLicense, marvelLongLicense));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidLicenseStorage() throws Exception {
|
||||||
|
LicensesManagerService licensesManagerService = masterLicensesManagerService();
|
||||||
|
ESLicense signedLicense = generateSignedLicense("shield", TimeValue.timeValueMinutes(2));
|
||||||
|
|
||||||
|
// modify content of signed license
|
||||||
|
ESLicense tamperedLicense = ESLicense.builder()
|
||||||
|
.fromLicenseSpec(signedLicense, signedLicense.signature())
|
||||||
|
.expiryDate(signedLicense.expiryDate() + 10 * 24 * 60 * 60 * 1000l)
|
||||||
|
.verify()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
registerAndAckSignedLicenses(licensesManagerService, Arrays.asList(tamperedLicense), LicensesStatus.INVALID);
|
||||||
|
|
||||||
|
// ensure that the invalid license never made it to cluster state
|
||||||
|
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
||||||
|
if (licensesMetaData != null) {
|
||||||
|
assertThat(licensesMetaData.getSignatures().size(), equalTo(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveLicenses() throws Exception {
|
||||||
|
LicensesManagerService licensesManagerService = masterLicensesManagerService();
|
||||||
|
|
||||||
|
// generate a trial license for one feature
|
||||||
|
final LicensesClientService clientService = licensesClientService();
|
||||||
|
final TestTrackingClientListener clientListener = new TestTrackingClientListener(false);
|
||||||
|
registerWithTrialLicense(clientService, clientListener, "shield", TimeValue.timeValueHours(1)).run();
|
||||||
|
|
||||||
|
// generate signed licenses for multiple features
|
||||||
|
ESLicense shieldShortLicense = generateSignedLicense("shield", TimeValue.timeValueHours(1));
|
||||||
|
ESLicense shieldLongLicense = generateSignedLicense("shield", TimeValue.timeValueHours(2));
|
||||||
|
ESLicense marvelShortLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(1));
|
||||||
|
ESLicense marvelLongLicense = generateSignedLicense("marvel", TimeValue.timeValueHours(2));
|
||||||
|
|
||||||
|
List<ESLicense> licenses = Arrays.asList(shieldLongLicense, shieldShortLicense, marvelLongLicense, marvelShortLicense);
|
||||||
|
Collections.shuffle(licenses);
|
||||||
|
registerAndAckSignedLicenses(licensesManagerService, licenses, LicensesStatus.VALID);
|
||||||
|
|
||||||
|
// remove license(s) for one feature out of two
|
||||||
|
removeAndAckSignedLicenses(licensesManagerService, Sets.newHashSet("shield"));
|
||||||
|
final ImmutableSet<String> licenseSignatures = masterLicenseManager().toSignatures(Arrays.asList(marvelLongLicense, marvelShortLicense));
|
||||||
|
LicensesMetaData licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
||||||
|
assertThat(licenseSignatures, equalTo(licensesMetaData.getSignatures()));
|
||||||
|
// check that trial license is not removed
|
||||||
|
assertThat(licensesMetaData.getEncodedTrialLicenses().size(), equalTo(1));
|
||||||
|
|
||||||
|
// remove license(s) for all features
|
||||||
|
removeAndAckSignedLicenses(licensesManagerService, Sets.newHashSet("shield", "marvel"));
|
||||||
|
licensesMetaData = clusterService().state().metaData().custom(LicensesMetaData.TYPE);
|
||||||
|
assertThat(licensesMetaData.getSignatures().size(), equalTo(0));
|
||||||
|
// check that trial license is not removed
|
||||||
|
assertThat(licensesMetaData.getEncodedTrialLicenses().size(), equalTo(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeAndAckSignedLicenses(final LicensesManagerService masterLicensesManagerService, final Set<String> featuresToDelete) {
|
||||||
|
DeleteLicenseRequest deleteLicenseRequest = new DeleteLicenseRequest(featuresToDelete.toArray(new String[featuresToDelete.size()]));
|
||||||
|
LicensesService.DeleteLicenseRequestHolder requestHolder = new LicensesService.DeleteLicenseRequestHolder(deleteLicenseRequest, "test");
|
||||||
|
final CountDownLatch latch = new CountDownLatch(1);
|
||||||
|
final AtomicBoolean success = new AtomicBoolean(false);
|
||||||
|
masterLicensesManagerService.removeLicenses(requestHolder, new ActionListener<ClusterStateUpdateResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
|
||||||
|
if (clusterStateUpdateResponse.isAcknowledged()) {
|
||||||
|
success.set(true);
|
||||||
|
}
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
latch.countDown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
fail(e.getMessage());
|
||||||
|
}
|
||||||
|
assertThat("remove license(s) failed", success.get(), equalTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private ESLicenseManager masterLicenseManager() {
|
||||||
|
InternalTestCluster clients = internalCluster();
|
||||||
|
return clients.getInstance(ESLicenseManager.class, clients.getMasterName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue