Initial node level tests; minor cleanup
Original commit: elastic/x-pack-elasticsearch@a917460b3c
This commit is contained in:
parent
941a440046
commit
ceaefcb2c8
|
@ -172,7 +172,7 @@ public class LicensesMetaData implements MetaData.Custom {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EnumSet<MetaData.XContentContext> context() {
|
public EnumSet<MetaData.XContentContext> context() {
|
||||||
return MetaData.API_ONLY;
|
return EnumSet.of(MetaData.XContentContext.GATEWAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -247,7 +247,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
LicensesMetaData currentLicensesMetaData = metaData.custom(LicensesMetaData.TYPE);
|
LicensesMetaData currentLicensesMetaData = metaData.custom(LicensesMetaData.TYPE);
|
||||||
final LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicensesMetaData);
|
final LicensesWrapper licensesWrapper = LicensesWrapper.wrap(currentLicensesMetaData);
|
||||||
// do not generate a trial license for a feature that already has a signed license
|
// do not generate a trial license for a feature that already has a signed license
|
||||||
if (!esLicenseManager.hasLicenseForFeature(request.feature, getEffectiveLicenses())) {
|
if (!hasLicenseForFeature(request.feature, currentLicensesMetaData)) {
|
||||||
licensesWrapper.addTrialLicense(generateTrialLicense(request.feature, request.duration, request.maxNodes));
|
licensesWrapper.addTrialLicense(generateTrialLicense(request.feature, request.duration, request.maxNodes));
|
||||||
}
|
}
|
||||||
mdBuilder.putCustom(LicensesMetaData.TYPE, licensesWrapper.createLicensesMetaData());
|
mdBuilder.putCustom(LicensesMetaData.TYPE, licensesWrapper.createLicensesMetaData());
|
||||||
|
@ -275,6 +275,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws ElasticsearchException {
|
protected void doStart() throws ElasticsearchException {
|
||||||
|
//Change to debug
|
||||||
|
logger.info("Started LicensesService");
|
||||||
if (DiscoveryNode.dataNode(settings) || DiscoveryNode.masterNode(settings)) {
|
if (DiscoveryNode.dataNode(settings) || DiscoveryNode.masterNode(settings)) {
|
||||||
clusterService.add(this);
|
clusterService.add(this);
|
||||||
}
|
}
|
||||||
|
@ -287,6 +289,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doClose() throws ElasticsearchException {
|
protected void doClose() throws ElasticsearchException {
|
||||||
|
logger.info("Closing LicensesService");
|
||||||
if (notificationScheduler != null) {
|
if (notificationScheduler != null) {
|
||||||
notificationScheduler.cancel(true);
|
notificationScheduler.cancel(true);
|
||||||
notificationScheduler = null;
|
notificationScheduler = null;
|
||||||
|
@ -310,6 +313,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
if (!pendingRegistrations.isEmpty()) {
|
if (!pendingRegistrations.isEmpty()) {
|
||||||
ListenerHolder pendingRegistrationLister;
|
ListenerHolder pendingRegistrationLister;
|
||||||
while ((pendingRegistrationLister = pendingRegistrations.poll()) != null) {
|
while ((pendingRegistrationLister = pendingRegistrations.poll()) != null) {
|
||||||
|
logger.info("trying to register pending listener for " + pendingRegistrationLister.feature);
|
||||||
registerListener(pendingRegistrationLister);
|
registerListener(pendingRegistrationLister);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -346,15 +350,20 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
public void register(String feature, TrialLicenseOptions trialLicenseOptions, Listener listener) {
|
public void register(String feature, TrialLicenseOptions trialLicenseOptions, Listener listener) {
|
||||||
final ListenerHolder listenerHolder = new ListenerHolder(feature, trialLicenseOptions, listener);
|
final ListenerHolder listenerHolder = new ListenerHolder(feature, trialLicenseOptions, listener);
|
||||||
registeredListeners.add(listenerHolder);
|
registeredListeners.add(listenerHolder);
|
||||||
|
|
||||||
//if (!clusterService.state().blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK)) {
|
|
||||||
registerListener(listenerHolder);
|
registerListener(listenerHolder);
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies new feature listener if it already has a signed license
|
||||||
|
* if new feature has a non-null trial license option, a master node request is made to generate the trial license
|
||||||
|
* if no trial license option is specified for the feature and no signed license is found,
|
||||||
|
* then notifies features to be disabled
|
||||||
|
*
|
||||||
|
* @param listenerHolder of the feature to register
|
||||||
|
*/
|
||||||
private void registerListener(final ListenerHolder listenerHolder) {
|
private void registerListener(final ListenerHolder listenerHolder) {
|
||||||
LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE);
|
LicensesMetaData currentMetaData = clusterService.state().metaData().custom(LicensesMetaData.TYPE);
|
||||||
if (!esLicenseManager.hasLicenseForFeature(listenerHolder.feature, getEffectiveLicenses())) {
|
if (!hasLicenseForFeature(listenerHolder.feature, currentMetaData)) {
|
||||||
// does not have actual license so generate a trial license
|
// does not have actual license so generate a trial license
|
||||||
TrialLicenseOptions options = listenerHolder.trialLicenseOptions;
|
TrialLicenseOptions options = listenerHolder.trialLicenseOptions;
|
||||||
if (options != null) {
|
if (options != null) {
|
||||||
|
@ -373,7 +382,6 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
} else {
|
} else {
|
||||||
// could not sent register trial license request to master
|
// could not sent register trial license request to master
|
||||||
pendingRegistrations.add(listenerHolder);
|
pendingRegistrations.add(listenerHolder);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -390,15 +398,17 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasLicenseForFeature(String feature, LicensesMetaData currentLicensesMetaData) {
|
||||||
|
return esLicenseManager.hasLicenseForFeature(feature, getEffectiveLicenses(currentLicensesMetaData));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private String executorName() {
|
private String executorName() {
|
||||||
return ThreadPool.Names.GENERIC;
|
return ThreadPool.Names.GENERIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, ESLicense> getEffectiveLicenses() {
|
public Map<String, ESLicense> getEffectiveLicenses(LicensesMetaData metaData) {
|
||||||
final ClusterState state = clusterService.state();
|
|
||||||
LicensesMetaData metaData = state.metaData().custom(LicensesMetaData.TYPE);
|
|
||||||
Map<String, ESLicense> map = new HashMap<>();
|
Map<String, ESLicense> map = new HashMap<>();
|
||||||
|
|
||||||
if (metaData != null) {
|
if (metaData != null) {
|
||||||
Set<ESLicense> esLicenses = new HashSet<>();
|
Set<ESLicense> esLicenses = new HashSet<>();
|
||||||
for (String signature : metaData.getSignatures()) {
|
for (String signature : metaData.getSignatures()) {
|
||||||
|
@ -473,8 +483,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
long offset = TimeValue.timeValueMinutes(1).getMillis();
|
long offset = TimeValue.timeValueMinutes(1).getMillis();
|
||||||
for (ListenerHolder listenerHolder : registeredListeners) {
|
for (ListenerHolder listenerHolder : registeredListeners) {
|
||||||
long expiryDate = -1l;
|
long expiryDate = -1l;
|
||||||
final Map<String, ESLicense> effectiveLicenses = getEffectiveLicenses();
|
if (hasLicenseForFeature(listenerHolder.feature, currentLicensesMetaData)) {
|
||||||
if (esLicenseManager.hasLicenseForFeature(listenerHolder.feature, effectiveLicenses)) {
|
final Map<String, ESLicense> effectiveLicenses = getEffectiveLicenses(currentLicensesMetaData);
|
||||||
expiryDate = effectiveLicenses.get(listenerHolder.feature).expiryDate();
|
expiryDate = effectiveLicenses.get(listenerHolder.feature).expiryDate();
|
||||||
} else {
|
} else {
|
||||||
final TrialLicense trialLicense = licensesWrapper.trialLicenses().getTrialLicense(listenerHolder.feature);
|
final TrialLicense trialLicense = licensesWrapper.trialLicenses().getTrialLicense(listenerHolder.feature);
|
||||||
|
|
|
@ -15,6 +15,8 @@ import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -98,6 +100,10 @@ public class TestUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void isSame(Collection<ESLicense> firstLicenses, Collection<ESLicense> secondLicenses) {
|
||||||
|
isSame(new HashSet<>(firstLicenses), new HashSet<>(secondLicenses));
|
||||||
|
}
|
||||||
|
|
||||||
public static void isSame(Set<ESLicense> firstLicenses, Set<ESLicense> secondLicenses) {
|
public static void isSame(Set<ESLicense> firstLicenses, Set<ESLicense> secondLicenses) {
|
||||||
|
|
||||||
// we do the build to make sure we weed out any expired licenses
|
// we do the build to make sure we weed out any expired licenses
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
* 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.ActionFuture;
|
||||||
|
import org.elasticsearch.client.Client;
|
||||||
|
import org.elasticsearch.client.ClusterAdminClient;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.common.settings.ImmutableSettings;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.license.TestUtils;
|
||||||
|
import org.elasticsearch.license.core.ESLicense;
|
||||||
|
import org.elasticsearch.license.core.ESLicenses;
|
||||||
|
import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder;
|
||||||
|
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||||
|
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||||
|
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||||
|
import org.elasticsearch.test.ElasticsearchIntegrationTest;
|
||||||
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
|
||||||
|
import static org.elasticsearch.test.ElasticsearchIntegrationTest.Scope.SUITE;
|
||||||
|
import static org.hamcrest.CoreMatchers.equalTo;
|
||||||
|
|
||||||
|
@ClusterScope(scope = SUITE, numDataNodes = 0)
|
||||||
|
public class LicensesServiceClusterRestartTest extends ElasticsearchIntegrationTest {
|
||||||
|
|
||||||
|
static String priKeyPath;
|
||||||
|
static String pubKeyPath;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Settings transportClientSettings() {
|
||||||
|
// Plugin should be loaded on the transport client as well
|
||||||
|
return settingsBuilder().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test @Ignore
|
||||||
|
public void test() throws Exception {
|
||||||
|
priKeyPath = Paths.get(LicensesServiceClusterRestartTest.class.getResource("/private.key").toURI()).toAbsolutePath().toString();
|
||||||
|
pubKeyPath = Paths.get(LicensesServiceClusterRestartTest.class.getResource("/public.key").toURI()).toAbsolutePath().toString();
|
||||||
|
|
||||||
|
logger.info("--> starting 1 nodes");
|
||||||
|
String node1 = internalCluster().startNode(settingsBuilder());
|
||||||
|
|
||||||
|
ensureGreen();
|
||||||
|
final List<ESLicense> esLicenses = putLicense(node1);
|
||||||
|
final Client startNodeClient = internalCluster().startNodeClient(settingsBuilder().build());
|
||||||
|
//TODO: just pass node name instead
|
||||||
|
getAndCheckLicense(startNodeClient, esLicenses);
|
||||||
|
|
||||||
|
logger.info("--> cluster state before full cluster restart");
|
||||||
|
ClusterState clusterState = client().admin().cluster().prepareState().get().getState();
|
||||||
|
logger.info("Cluster state: {}", clusterState);
|
||||||
|
|
||||||
|
logger.info("--> restart all nodes");
|
||||||
|
internalCluster().fullRestart();
|
||||||
|
ensureYellow();
|
||||||
|
|
||||||
|
logger.info("--> cluster state after full cluster restart");
|
||||||
|
clusterState = client().admin().cluster().prepareState().get().getState();
|
||||||
|
logger.info("Cluster state: {}", clusterState);
|
||||||
|
|
||||||
|
getAndCheckLicense(internalCluster().startNodeClient(settingsBuilder().build()), esLicenses);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ESLicense> putLicense(String node) throws Exception {
|
||||||
|
|
||||||
|
final ClusterAdminClient cluster = internalCluster().client(node).admin().cluster();
|
||||||
|
|
||||||
|
Map<String, TestUtils.FeatureAttributes> map = new HashMap<>();
|
||||||
|
TestUtils.FeatureAttributes featureAttributes =
|
||||||
|
new TestUtils.FeatureAttributes("shield", "subscription", "platinum", "foo bar Inc.", "elasticsearch", 2, "2014-12-13", "2015-12-13");
|
||||||
|
map.put(TestUtils.SHIELD, featureAttributes);
|
||||||
|
String licenseString = TestUtils.generateESLicenses(map);
|
||||||
|
String licenseOutput = TestUtils.runLicenseGenerationTool(licenseString, pubKeyPath, priKeyPath);
|
||||||
|
|
||||||
|
PutLicenseRequestBuilder putLicenseRequestBuilder = new PutLicenseRequestBuilder(cluster);
|
||||||
|
final List<ESLicense> putLicenses = ESLicenses.fromSource(licenseOutput);
|
||||||
|
assertThat(putLicenses.size(), equalTo(1));
|
||||||
|
putLicenseRequestBuilder.setLicense(putLicenses);
|
||||||
|
ensureGreen();
|
||||||
|
|
||||||
|
final ActionFuture<PutLicenseResponse> putLicenseFuture = putLicenseRequestBuilder.execute();
|
||||||
|
|
||||||
|
final PutLicenseResponse putLicenseResponse = putLicenseFuture.get();
|
||||||
|
assertTrue(putLicenseResponse.isAcknowledged());
|
||||||
|
|
||||||
|
return putLicenses;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getAndCheckLicense(Client client, List<ESLicense> license) {
|
||||||
|
final ClusterAdminClient cluster = client.admin().cluster();
|
||||||
|
final GetLicenseResponse response = new GetLicenseRequestBuilder(cluster).get();
|
||||||
|
assertThat(response.licenses().size(), equalTo(1));
|
||||||
|
TestUtils.isSame(license, response.licenses());
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImmutableSettings.Builder settingsBuilder() {
|
||||||
|
return ImmutableSettings.settingsBuilder()
|
||||||
|
.put("gateway.type", "local")
|
||||||
|
.put("plugin.types", LicensePlugin.class.getName());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue