implemented Trial licenses
Original commit: elastic/x-pack-elasticsearch@64b987a991
This commit is contained in:
parent
f05ccaa3f9
commit
6b208bce8f
|
@ -252,7 +252,15 @@ public class ESLicenseManager {
|
||||||
return convertToESLicense(license);
|
return convertToESLicense(license);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESLicense decryptAndVerifyESLicense(SignedLicense signedLicense, String signature) {
|
||||||
|
return convertToESLicense(this.licenseManager.decryptAndVerifyLicense(signedLicense), signature);
|
||||||
|
}
|
||||||
|
|
||||||
static ESLicense convertToESLicense(License license) {
|
static ESLicense convertToESLicense(License license) {
|
||||||
|
return convertToESLicense(license, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ESLicense convertToESLicense(License license, String signature) {
|
||||||
final LicenseBuilders.LicenseBuilder licenseBuilder = LicenseBuilders.licenseBuilder(false);
|
final LicenseBuilders.LicenseBuilder licenseBuilder = LicenseBuilders.licenseBuilder(false);
|
||||||
licenseBuilder
|
licenseBuilder
|
||||||
.expiryDate(license.getGoodBeforeDate())
|
.expiryDate(license.getGoodBeforeDate())
|
||||||
|
@ -261,6 +269,10 @@ public class ESLicenseManager {
|
||||||
.issuedTo(license.getHolder())
|
.issuedTo(license.getHolder())
|
||||||
.issuer(license.getIssuer());
|
.issuer(license.getIssuer());
|
||||||
|
|
||||||
|
if (signature != null) {
|
||||||
|
licenseBuilder.signature(signature);
|
||||||
|
}
|
||||||
|
|
||||||
assert license.getFeatures().size() == 4 : "one license should have only four feature";
|
assert license.getFeatures().size() == 4 : "one license should have only four feature";
|
||||||
String maxNodesPrefix = "maxNodes:";
|
String maxNodesPrefix = "maxNodes:";
|
||||||
String typePrefix = "type:";
|
String typePrefix = "type:";
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.license.manager;
|
package org.elasticsearch.license.manager;
|
||||||
|
|
||||||
import net.nicholaswilliams.java.licensing.LicenseManager;
|
|
||||||
import net.nicholaswilliams.java.licensing.ObjectSerializer;
|
import net.nicholaswilliams.java.licensing.ObjectSerializer;
|
||||||
import net.nicholaswilliams.java.licensing.SignedLicense;
|
import net.nicholaswilliams.java.licensing.SignedLicense;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
@ -20,22 +19,22 @@ import static org.elasticsearch.license.core.ESLicenses.ESLicense;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
public static ESLicenses getESLicensesFromSignatures(final LicenseManager licenseManager, Set<String> signatures) {
|
public static ESLicenses getESLicensesFromSignatures(final Set<String> signatures) {
|
||||||
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
|
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
|
||||||
for (String signature : signatures) {
|
for (String signature : signatures) {
|
||||||
licensesBuilder.license(getESLicenseFromSignature(licenseManager, signature));
|
licensesBuilder.license(getESLicenseFromSignature(signature));
|
||||||
}
|
}
|
||||||
return licensesBuilder.build();
|
return licensesBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ESLicense getESLicenseFromSignature(LicenseManager licenseManager, String signature) {
|
private static ESLicense getESLicenseFromSignature(String signature) {
|
||||||
byte[] signatureBytes = Base64.decodeBase64(signature);
|
byte[] signatureBytes = Base64.decodeBase64(signature);
|
||||||
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
|
ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
|
||||||
byteBuffer = (ByteBuffer) byteBuffer.position(13);
|
byteBuffer = (ByteBuffer) byteBuffer.position(13);
|
||||||
int start = byteBuffer.getInt();
|
int start = byteBuffer.getInt();
|
||||||
SignedLicense signedLicense = new ObjectSerializer()
|
SignedLicense signedLicense = new ObjectSerializer()
|
||||||
.readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length));
|
.readObject(SignedLicense.class, Arrays.copyOfRange(signatureBytes, start, signatureBytes.length));
|
||||||
return ESLicenseManager.convertToESLicense(licenseManager.decryptAndVerifyLicense(signedLicense));
|
return ESLicenseManager.getInstance().decryptAndVerifyESLicense(signedLicense, signature);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) {
|
public static boolean isSame(ESLicenses firstLicenses, ESLicenses secondLicenses) {
|
||||||
|
|
|
@ -10,16 +10,19 @@ import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.license.core.ESLicenses;
|
import org.elasticsearch.license.core.ESLicenses;
|
||||||
import org.elasticsearch.license.core.LicenseBuilders;
|
import org.elasticsearch.license.core.LicenseBuilders;
|
||||||
|
import org.elasticsearch.license.plugin.core.TrialLicenses;
|
||||||
|
import org.elasticsearch.license.plugin.core.TrialLicensesBuilder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.elasticsearch.license.core.ESLicenses.*;
|
import static org.elasticsearch.license.core.ESLicenses.*;
|
||||||
|
import static org.elasticsearch.license.plugin.core.TrialLicenses.TrialLicense;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
|
|
||||||
public static ESLicenses readLicensesFrom(StreamInput in) throws IOException {
|
public static ESLicenses readGeneratedLicensesFrom(StreamInput in) throws IOException {
|
||||||
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
|
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
|
||||||
boolean exists = in.readBoolean();
|
boolean exists = in.readBoolean();
|
||||||
if (exists) {
|
if (exists) {
|
||||||
|
@ -32,7 +35,7 @@ public class Utils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeLicensesTo(ESLicenses esLicenses, StreamOutput out) throws IOException {
|
public static void writeGeneratedLicensesTo(ESLicenses esLicenses, StreamOutput out) throws IOException {
|
||||||
if (esLicenses == null) {
|
if (esLicenses == null) {
|
||||||
out.writeBoolean(false);
|
out.writeBoolean(false);
|
||||||
return;
|
return;
|
||||||
|
@ -44,6 +47,52 @@ public class Utils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static TrialLicenses readTrialLicensesFrom(StreamInput in) throws IOException {
|
||||||
|
final TrialLicensesBuilder licensesBuilder = TrialLicensesBuilder.trialLicensesBuilder();
|
||||||
|
boolean exists = in.readBoolean();
|
||||||
|
if (exists) {
|
||||||
|
int size = in.readVInt();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
licensesBuilder.license(trialLicenseFromMap(in.readMap()));
|
||||||
|
}
|
||||||
|
return licensesBuilder.build();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeTrialLicensesTo(TrialLicenses trialLicenses, StreamOutput out) throws IOException {
|
||||||
|
if (trialLicenses == null) {
|
||||||
|
out.writeBoolean(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
out.writeBoolean(true);
|
||||||
|
out.writeVInt(trialLicenses.trialLicenses().size());
|
||||||
|
for (TrialLicense trialLicense : trialLicenses) {
|
||||||
|
out.writeMap(trialLicenseAsMap(trialLicense));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, Object> trialLicenseAsMap(TrialLicense trialLicense) {
|
||||||
|
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
|
||||||
|
builder.put(TrialLicenseFields.UID, trialLicense.uid());
|
||||||
|
builder.put(TrialLicenseFields.ISSUE_DATE, trialLicense.issueDate());
|
||||||
|
builder.put(TrialLicenseFields.EXPIRY_DATE, trialLicense.expiryDate());
|
||||||
|
builder.put(TrialLicenseFields.MAX_NODES, trialLicense.maxNodes());
|
||||||
|
builder.put(TrialLicenseFields.FEATURE, trialLicense.feature().string());
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrialLicense trialLicenseFromMap(Map<String, Object> map) {
|
||||||
|
return TrialLicensesBuilder.trialLicenseBuilder()
|
||||||
|
.uid((String) map.get(TrialLicenseFields.UID))
|
||||||
|
.maxNodes((int) map.get(TrialLicenseFields.MAX_NODES))
|
||||||
|
.feature(FeatureType.fromString((String) map.get(TrialLicenseFields.FEATURE)))
|
||||||
|
.issueDate((long) map.get(TrialLicenseFields.ISSUE_DATE))
|
||||||
|
.expiryDate((long) map.get(TrialLicenseFields.EXPIRY_DATE))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static Map<String, Object> licenseAsMap(ESLicense esLicense) {
|
public static Map<String, Object> licenseAsMap(ESLicense esLicense) {
|
||||||
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
|
ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
|
||||||
builder.put(LicenseFields.UID, esLicense.uid());
|
builder.put(LicenseFields.UID, esLicense.uid());
|
||||||
|
@ -73,6 +122,15 @@ public class Utils {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final static class TrialLicenseFields {
|
||||||
|
private final static String UID = "uid";
|
||||||
|
private final static String ISSUE_DATE = "issue_date";
|
||||||
|
private final static String EXPIRY_DATE = "expiry_date";
|
||||||
|
private final static String MAX_NODES = "max_nodes";
|
||||||
|
private final static String FEATURE = "feature";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
final static class LicenseFields {
|
final static class LicenseFields {
|
||||||
private final static String UID = "uid";
|
private final static String UID = "uid";
|
||||||
private final static String TYPE = "type";
|
private final static String TYPE = "type";
|
||||||
|
|
|
@ -13,8 +13,8 @@ import org.elasticsearch.license.core.LicenseBuilders;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.elasticsearch.license.plugin.action.Utils.readLicensesFrom;
|
import static org.elasticsearch.license.plugin.action.Utils.readGeneratedLicensesFrom;
|
||||||
import static org.elasticsearch.license.plugin.action.Utils.writeLicensesTo;
|
import static org.elasticsearch.license.plugin.action.Utils.writeGeneratedLicensesTo;
|
||||||
|
|
||||||
public class GetLicenseResponse extends ActionResponse {
|
public class GetLicenseResponse extends ActionResponse {
|
||||||
|
|
||||||
|
@ -34,13 +34,13 @@ public class GetLicenseResponse extends ActionResponse {
|
||||||
@Override
|
@Override
|
||||||
public void readFrom(StreamInput in) throws IOException {
|
public void readFrom(StreamInput in) throws IOException {
|
||||||
super.readFrom(in);
|
super.readFrom(in);
|
||||||
licenses = readLicensesFrom(in);
|
licenses = readGeneratedLicensesFrom(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
super.writeTo(out);
|
super.writeTo(out);
|
||||||
writeLicensesTo(licenses, out);
|
writeGeneratedLicensesTo(licenses, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -53,6 +53,10 @@ public class TransportGetLicenseAction extends TransportMasterNodeReadOperationA
|
||||||
protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse> listener) throws ElasticsearchException {
|
protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse> listener) throws ElasticsearchException {
|
||||||
MetaData metaData = state.metaData();
|
MetaData metaData = state.metaData();
|
||||||
LicensesMetaData licenses = metaData.custom(LicensesMetaData.TYPE);
|
LicensesMetaData licenses = metaData.custom(LicensesMetaData.TYPE);
|
||||||
listener.onResponse(new GetLicenseResponse(licenses));
|
if (licenses != null) {
|
||||||
|
listener.onResponse(new GetLicenseResponse(licenses.getLicenses()));
|
||||||
|
} else {
|
||||||
|
listener.onResponse(new GetLicenseResponse());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -15,8 +15,8 @@ import org.elasticsearch.license.core.LicenseUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static org.elasticsearch.license.plugin.action.Utils.readLicensesFrom;
|
import static org.elasticsearch.license.plugin.action.Utils.readGeneratedLicensesFrom;
|
||||||
import static org.elasticsearch.license.plugin.action.Utils.writeLicensesTo;
|
import static org.elasticsearch.license.plugin.action.Utils.writeGeneratedLicensesTo;
|
||||||
|
|
||||||
public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
|
public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
|
||||||
|
|
||||||
|
@ -54,14 +54,14 @@ public class PutLicenseRequest extends AcknowledgedRequest<PutLicenseRequest> {
|
||||||
@Override
|
@Override
|
||||||
public void readFrom(StreamInput in) throws IOException {
|
public void readFrom(StreamInput in) throws IOException {
|
||||||
super.readFrom(in);
|
super.readFrom(in);
|
||||||
license = readLicensesFrom(in);
|
license = readGeneratedLicensesFrom(in);
|
||||||
readTimeout(in);
|
readTimeout(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(StreamOutput out) throws IOException {
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
super.writeTo(out);
|
super.writeTo(out);
|
||||||
writeLicensesTo(license, out);
|
writeGeneratedLicensesTo(license, out);
|
||||||
writeTimeout(out);
|
writeTimeout(out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
package org.elasticsearch.license.plugin.core;
|
package org.elasticsearch.license.plugin.core;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchParseException;
|
import org.elasticsearch.ElasticsearchIllegalArgumentException;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.common.collect.ImmutableMap;
|
import org.elasticsearch.common.collect.ImmutableMap;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
@ -14,39 +14,87 @@ import org.elasticsearch.common.xcontent.ToXContent;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
import org.elasticsearch.common.xcontent.XContentParser;
|
import org.elasticsearch.common.xcontent.XContentParser;
|
||||||
import org.elasticsearch.license.core.ESLicenses;
|
import org.elasticsearch.license.core.ESLicenses;
|
||||||
|
import org.elasticsearch.license.core.LicenseBuilders;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.elasticsearch.license.core.ESLicenses.ESLicense;
|
||||||
|
import static org.elasticsearch.license.core.ESLicenses.FeatureType;
|
||||||
import static org.elasticsearch.license.plugin.action.Utils.*;
|
import static org.elasticsearch.license.plugin.action.Utils.*;
|
||||||
|
import static org.elasticsearch.license.plugin.core.TrialLicenses.TrialLicense;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains metadata about registered licenses
|
* Contains metadata about registered licenses
|
||||||
*
|
*
|
||||||
* TODO: add trial licenses to MetaData
|
* TODO: store only signatures rather than the whole licenses json in cluster state
|
||||||
*/
|
*/
|
||||||
public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicenses {
|
public class LicensesMetaData implements MetaData.Custom {
|
||||||
|
|
||||||
public static final String TYPE = "licenses";
|
public static final String TYPE = "licenses";
|
||||||
|
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
|
|
||||||
private final ImmutableMap<FeatureType, ESLicense> licenses;
|
private final ImmutableMap<FeatureType, ESLicense> licensesMap;
|
||||||
|
|
||||||
|
private final ImmutableMap<FeatureType, TrialLicense> trialLicensesMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs new licenses metadata
|
* Constructs new licenses metadata
|
||||||
*
|
*
|
||||||
* @param esLicenses list of esLicense
|
* @param esLicenses list of esLicense
|
||||||
*/
|
*/
|
||||||
public LicensesMetaData(List<ESLicense> esLicenses) {
|
public LicensesMetaData(ESLicenses esLicenses, TrialLicenses trialLicenses) {
|
||||||
this.licenses = map(esLicenses);
|
this.licensesMap = map(esLicenses);
|
||||||
|
this.trialLicensesMap = map(trialLicenses);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LicensesMetaData(ESLicenses esLicenses) {
|
|
||||||
this.licenses = map(esLicenses);
|
public ESLicenses getLicenses() {
|
||||||
|
return new ESLicenses() {
|
||||||
|
@Override
|
||||||
|
public Collection<ESLicense> licenses() {
|
||||||
|
return licensesMap.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ImmutableMap<FeatureType, ESLicense> map(Iterable<ESLicense> esLicenses) {
|
@Override
|
||||||
|
public Set<FeatureType> features() {
|
||||||
|
return licensesMap.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ESLicense get(FeatureType featureType) {
|
||||||
|
return licensesMap.get(featureType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<ESLicense> iterator() {
|
||||||
|
return licensesMap.values().iterator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrialLicenses getTrialLicenses() {
|
||||||
|
return new TrialLicenses() {
|
||||||
|
@Override
|
||||||
|
public Collection<TrialLicense> trialLicenses() {
|
||||||
|
return trialLicensesMap.values();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TrialLicense getTrialLicense(FeatureType featureType) {
|
||||||
|
return trialLicensesMap.get(featureType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<TrialLicense> iterator() {
|
||||||
|
return trialLicensesMap.values().iterator();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static ImmutableMap<FeatureType, ESLicense> map(ESLicenses esLicenses) {
|
||||||
final ImmutableMap.Builder<FeatureType, ESLicense> builder = ImmutableMap.builder();
|
final ImmutableMap.Builder<FeatureType, ESLicense> builder = ImmutableMap.builder();
|
||||||
if (esLicenses != null) {
|
if (esLicenses != null) {
|
||||||
for (ESLicense esLicense : esLicenses) {
|
for (ESLicense esLicense : esLicenses) {
|
||||||
|
@ -56,37 +104,14 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private static ImmutableMap<FeatureType, TrialLicense> map(TrialLicenses trialLicenses) {
|
||||||
public Collection<ESLicense> licenses() {
|
final ImmutableMap.Builder<FeatureType, TrialLicense> builder = ImmutableMap.builder();
|
||||||
return licenses.values();
|
if (trialLicenses != null) {
|
||||||
|
for (TrialLicense esLicense : trialLicenses) {
|
||||||
|
builder.put(esLicense.feature(), esLicense);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Set<FeatureType> features() {
|
|
||||||
return licenses.keySet();
|
|
||||||
}
|
}
|
||||||
|
return builder.build();
|
||||||
|
|
||||||
@Override
|
|
||||||
public ESLicense get(FeatureType featureType) {
|
|
||||||
return licenses.get(featureType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<ESLicense> iterator() {
|
|
||||||
return licenses.values().iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<TrialLicense> trialLicenses() {
|
|
||||||
//todo trial license functionality
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TrialLicense getTrialLicense(FeatureType featureType) {
|
|
||||||
//todo trial license functionality
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -107,7 +132,13 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public LicensesMetaData readFrom(StreamInput in) throws IOException {
|
public LicensesMetaData readFrom(StreamInput in) throws IOException {
|
||||||
return new LicensesMetaData(readLicensesFrom(in));
|
ESLicenses esLicenses = null;
|
||||||
|
TrialLicenses trialLicenses = null;
|
||||||
|
if (in.readBoolean()) {
|
||||||
|
esLicenses = readGeneratedLicensesFrom(in);
|
||||||
|
trialLicenses = readTrialLicensesFrom(in);
|
||||||
|
}
|
||||||
|
return new LicensesMetaData(esLicenses, trialLicenses);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,7 +146,13 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void writeTo(LicensesMetaData licensesMetaData, StreamOutput out) throws IOException {
|
public void writeTo(LicensesMetaData licensesMetaData, StreamOutput out) throws IOException {
|
||||||
writeLicensesTo(licensesMetaData, out);
|
if (licensesMetaData == null) {
|
||||||
|
out.writeBoolean(false);
|
||||||
|
} else {
|
||||||
|
out.writeBoolean(true);
|
||||||
|
writeGeneratedLicensesTo(licensesMetaData.getLicenses(), out);
|
||||||
|
writeTrialLicensesTo(licensesMetaData.getTrialLicenses(), out);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,25 +162,27 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
|
||||||
public LicensesMetaData fromXContent(XContentParser parser) throws IOException {
|
public LicensesMetaData fromXContent(XContentParser parser) throws IOException {
|
||||||
|
|
||||||
XContentParser.Token token;
|
XContentParser.Token token;
|
||||||
List<ESLicense> licenses = null;
|
final LicenseBuilders.LicensesBuilder licensesBuilder = LicenseBuilders.licensesBuilder();
|
||||||
|
final TrialLicensesBuilder trialLicensesBuilder = TrialLicensesBuilder.trialLicensesBuilder();
|
||||||
String fieldName = null;
|
String fieldName = null;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||||
if (token == XContentParser.Token.FIELD_NAME) {
|
if (token == XContentParser.Token.FIELD_NAME) {
|
||||||
fieldName = parser.currentName();
|
fieldName = parser.currentName();
|
||||||
}
|
}
|
||||||
if (fieldName != null && fieldName.equals(Fields.LICENSES)) {
|
if (fieldName != null) {
|
||||||
if (licenses == null) {
|
if (fieldName.equals(Fields.LICENSES)) {
|
||||||
licenses = new ArrayList<>();
|
|
||||||
}
|
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
licenses.add(licenseFromMap(parser.map()));
|
licensesBuilder.license(licenseFromMap(parser.map()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fieldName.equals(Fields.TRIAL_LICENSES)) {
|
||||||
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
|
trialLicensesBuilder.license(trialLicenseFromMap(parser.map()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (licenses == null) {
|
|
||||||
throw new ElasticsearchParseException("failed to parse licenses: expected ['" + Fields.LICENSES + "']");
|
|
||||||
}
|
}
|
||||||
return new LicensesMetaData(licenses);
|
return new LicensesMetaData(licensesBuilder.build(), trialLicensesBuilder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -153,10 +192,16 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
|
||||||
public void toXContent(LicensesMetaData licensesMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
public void toXContent(LicensesMetaData licensesMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException {
|
||||||
builder.startObject();
|
builder.startObject();
|
||||||
builder.startArray(Fields.LICENSES);
|
builder.startArray(Fields.LICENSES);
|
||||||
for (ESLicense license : licensesMetaData.licenses()) {
|
for (ESLicense license : licensesMetaData.getLicenses()) {
|
||||||
builder.map(licenseAsMap(license));
|
builder.map(licenseAsMap(license));
|
||||||
}
|
}
|
||||||
builder.endArray();
|
builder.endArray();
|
||||||
|
|
||||||
|
builder.startArray(Fields.TRIAL_LICENSES);
|
||||||
|
for (TrialLicense license : licensesMetaData.getTrialLicenses()) {
|
||||||
|
builder.map(trialLicenseAsMap(license));
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
builder.endObject();
|
builder.endObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +213,7 @@ public class LicensesMetaData implements MetaData.Custom, ESLicenses, TrialLicen
|
||||||
|
|
||||||
private final static class Fields {
|
private final static class Fields {
|
||||||
private static final String LICENSES = "licenses";
|
private static final String LICENSES = "licenses";
|
||||||
|
private static final String TRIAL_LICENSES = "trial_licenses";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -7,12 +7,17 @@ package org.elasticsearch.license.plugin.core;
|
||||||
|
|
||||||
import org.elasticsearch.ElasticsearchException;
|
import org.elasticsearch.ElasticsearchException;
|
||||||
import org.elasticsearch.action.ActionListener;
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
||||||
import org.elasticsearch.cluster.*;
|
import org.elasticsearch.cluster.*;
|
||||||
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
import org.elasticsearch.cluster.ack.ClusterStateUpdateResponse;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
import org.elasticsearch.cluster.node.DiscoveryNode;
|
import org.elasticsearch.cluster.node.DiscoveryNode;
|
||||||
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||||
import org.elasticsearch.common.inject.Inject;
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.license.core.ESLicenses;
|
import org.elasticsearch.license.core.ESLicenses;
|
||||||
import org.elasticsearch.license.core.LicenseBuilders;
|
import org.elasticsearch.license.core.LicenseBuilders;
|
||||||
|
@ -23,6 +28,7 @@ import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||||
import org.elasticsearch.node.Node;
|
import org.elasticsearch.node.Node;
|
||||||
import org.elasticsearch.node.internal.InternalNode;
|
import org.elasticsearch.node.internal.InternalNode;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -60,7 +66,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
@Override
|
@Override
|
||||||
public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener) {
|
public void registerLicenses(final PutLicenseRequestHolder requestHolder, final ActionListener<ClusterStateUpdateResponse> listener) {
|
||||||
final PutLicenseRequest request = requestHolder.request;
|
final PutLicenseRequest request = requestHolder.request;
|
||||||
final LicensesMetaData newLicenseMetaData = new LicensesMetaData(request.license());
|
final ESLicenses newLicenses = request.license();
|
||||||
clusterService.submitStateUpdateTask(requestHolder.source, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, listener) {
|
clusterService.submitStateUpdateTask(requestHolder.source, new AckedClusterStateUpdateTask<ClusterStateUpdateResponse>(request, listener) {
|
||||||
@Override
|
@Override
|
||||||
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
|
protected ClusterStateUpdateResponse newResponse(boolean acknowledged) {
|
||||||
|
@ -73,15 +79,15 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||||
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
||||||
|
|
||||||
esLicenseManager.verifyLicenses(newLicenseMetaData);
|
esLicenseManager.verifyLicenses(newLicenses);
|
||||||
|
|
||||||
if (currentLicenses == null) {
|
if (currentLicenses == null) {
|
||||||
// no licenses were registered
|
// no licenses were registered
|
||||||
currentLicenses = newLicenseMetaData;
|
currentLicenses = new LicensesMetaData(newLicenses, null);
|
||||||
} else {
|
} else {
|
||||||
// merge previous license with new one
|
// merge previous license with new one
|
||||||
//TODO: proper merge for trial licenses
|
ESLicenses mergedLicenses = LicenseBuilders.merge(currentLicenses.getLicenses(), newLicenses);
|
||||||
currentLicenses = new LicensesMetaData(LicenseBuilders.merge(currentLicenses, newLicenseMetaData));
|
currentLicenses = new LicensesMetaData(mergedLicenses, currentLicenses.getTrialLicenses());
|
||||||
}
|
}
|
||||||
|
|
||||||
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
||||||
|
@ -109,7 +115,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
|
|
||||||
if (currentLicenses != null) {
|
if (currentLicenses != null) {
|
||||||
//TODO: proper delete for trial licenses
|
//TODO: proper delete for trial licenses
|
||||||
currentLicenses = new LicensesMetaData(LicenseBuilders.removeFeatures(currentLicenses, featuresToDelete));
|
final ESLicenses newLicenses = LicenseBuilders.removeFeatures(currentLicenses.getLicenses(), featuresToDelete);
|
||||||
|
currentLicenses = new LicensesMetaData(newLicenses, currentLicenses.getTrialLicenses());
|
||||||
}
|
}
|
||||||
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
||||||
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||||
|
@ -117,6 +124,44 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: hook this up
|
||||||
|
private void registerTrialLicense(final TrialLicenses.TrialLicense trialLicense) {
|
||||||
|
clusterService.submitStateUpdateTask("register trial license []", new ProcessedClusterStateUpdateTask() {
|
||||||
|
@Override
|
||||||
|
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||||
|
MetaData metaData = currentState.metaData();
|
||||||
|
MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
|
||||||
|
LicensesMetaData currentLicenses = metaData.custom(LicensesMetaData.TYPE);
|
||||||
|
TrialLicensesBuilder newTrialLicenses = TrialLicensesBuilder.trialLicensesBuilder().license(trialLicense);
|
||||||
|
if (currentLicenses != null) {
|
||||||
|
if (currentLicenses.getTrialLicenses() != null) {
|
||||||
|
// had previous trial licenses
|
||||||
|
newTrialLicenses = newTrialLicenses.licenses(currentLicenses.getTrialLicenses());
|
||||||
|
currentLicenses = new LicensesMetaData(currentLicenses.getLicenses(), newTrialLicenses.build());
|
||||||
|
} else {
|
||||||
|
// had no previous trial license
|
||||||
|
currentLicenses = new LicensesMetaData(currentLicenses.getLicenses(), newTrialLicenses.build());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// had no license meta data
|
||||||
|
currentLicenses = new LicensesMetaData(null, newTrialLicenses.build());
|
||||||
|
}
|
||||||
|
mdBuilder.putCustom(LicensesMetaData.TYPE, currentLicenses);
|
||||||
|
return ClusterState.builder(currentState).metaData(mdBuilder).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(String source, @Nullable Throwable t) {
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws ElasticsearchException {
|
protected void doStart() throws ElasticsearchException {
|
||||||
clusterService = node.injector().getInstance(ClusterService.class);
|
clusterService = node.injector().getInstance(ClusterService.class);
|
||||||
|
@ -188,4 +233,36 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
this.source = source;
|
this.source = source;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TrialLicenses.TrialLicense generateTrialLicense(String feature, int durationInDays, int maxNodes) {
|
||||||
|
return TrialLicensesBuilder.trialLicenseBuilder()
|
||||||
|
.issueDate(System.currentTimeMillis())
|
||||||
|
.durationInDays(durationInDays)
|
||||||
|
.feature(ESLicenses.FeatureType.fromString(feature))
|
||||||
|
.maxNodes(maxNodes)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PutTrialLicenseRequest extends AcknowledgedRequest<PutTrialLicenseRequest> {
|
||||||
|
|
||||||
|
private PutTrialLicenseRequest() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionRequestValidationException validate() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void readFrom(StreamInput in) throws IOException {
|
||||||
|
super.readFrom(in);
|
||||||
|
readTimeout(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
super.writeTo(out);
|
||||||
|
writeTimeout(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.util.Collection;
|
||||||
|
|
||||||
import static org.elasticsearch.license.core.ESLicenses.FeatureType;
|
import static org.elasticsearch.license.core.ESLicenses.FeatureType;
|
||||||
|
|
||||||
public interface TrialLicenses {
|
public interface TrialLicenses extends Iterable<TrialLicenses.TrialLicense> {
|
||||||
|
|
||||||
public Collection<TrialLicense> trialLicenses();
|
public Collection<TrialLicense> trialLicenses();
|
||||||
|
|
||||||
|
@ -22,5 +22,10 @@ public interface TrialLicenses {
|
||||||
public long issueDate();
|
public long issueDate();
|
||||||
|
|
||||||
public long expiryDate();
|
public long expiryDate();
|
||||||
|
|
||||||
|
public int maxNodes();
|
||||||
|
|
||||||
|
public String uid();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,29 @@ public class TrialLicensesBuilder {
|
||||||
return new TrialLicensesBuilder();
|
return new TrialLicensesBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ImmutableMap.Builder<ESLicenses.FeatureType, TrialLicense> licenseBuilder = ImmutableMap.builder();
|
public static TrialLicenseBuilder trialLicenseBuilder() {
|
||||||
|
return new TrialLicenseBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static TrialLicenses merge(TrialLicenses trialLicenses, TrialLicenses mergeTrialLicenses) {
|
||||||
|
if (trialLicenses == null && mergeTrialLicenses == null) {
|
||||||
|
throw new IllegalArgumentException("both licenses can not be null");
|
||||||
|
} else if (trialLicenses == null) {
|
||||||
|
return mergeTrialLicenses;
|
||||||
|
} else if (mergeTrialLicenses == null) {
|
||||||
|
return trialLicenses;
|
||||||
|
} else {
|
||||||
|
return trialLicensesBuilder()
|
||||||
|
.licenses(trialLicenses.trialLicenses())
|
||||||
|
.licenses(mergeTrialLicenses.trialLicenses())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ImmutableMap.Builder<ESLicenses.FeatureType, TrialLicense> licenseBuilder;
|
||||||
|
|
||||||
public TrialLicensesBuilder() {
|
public TrialLicensesBuilder() {
|
||||||
|
licenseBuilder = ImmutableMap.builder();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrialLicensesBuilder license(TrialLicense trialLicense) {
|
public TrialLicensesBuilder license(TrialLicense trialLicense) {
|
||||||
|
@ -31,6 +51,10 @@ public class TrialLicensesBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TrialLicensesBuilder licenses(TrialLicenses trialLicenses) {
|
||||||
|
return licenses(trialLicenses.trialLicenses());
|
||||||
|
}
|
||||||
|
|
||||||
public TrialLicensesBuilder licenses(Collection<TrialLicense> trialLicenses) {
|
public TrialLicensesBuilder licenses(Collection<TrialLicense> trialLicenses) {
|
||||||
for (TrialLicense trialLicense : trialLicenses) {
|
for (TrialLicense trialLicense : trialLicenses) {
|
||||||
license(trialLicense);
|
license(trialLicense);
|
||||||
|
@ -52,6 +76,10 @@ public class TrialLicensesBuilder {
|
||||||
return licenseMap.get(featureType);
|
return licenseMap.get(featureType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<TrialLicense> iterator() {
|
||||||
|
return licenseMap.values().iterator();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,10 +88,22 @@ public class TrialLicensesBuilder {
|
||||||
private long expiryDate = -1;
|
private long expiryDate = -1;
|
||||||
private long issueDate = -1;
|
private long issueDate = -1;
|
||||||
private int durationInDays = -1;
|
private int durationInDays = -1;
|
||||||
|
private int maxNodes = -1;
|
||||||
|
private String uid = null;
|
||||||
|
|
||||||
public TrialLicenseBuilder() {
|
public TrialLicenseBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TrialLicenseBuilder uid(String uid) {
|
||||||
|
this.uid = uid;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrialLicenseBuilder maxNodes(int maxNodes) {
|
||||||
|
this.maxNodes = maxNodes;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TrialLicenseBuilder feature(ESLicenses.FeatureType featureType) {
|
public TrialLicenseBuilder feature(ESLicenses.FeatureType featureType) {
|
||||||
this.featureType = featureType;
|
this.featureType = featureType;
|
||||||
return this;
|
return this;
|
||||||
|
@ -90,6 +130,9 @@ public class TrialLicensesBuilder {
|
||||||
assert durationInDays != -1;
|
assert durationInDays != -1;
|
||||||
expiryDate = DateUtils.expiryDateAfterDays(issueDate, durationInDays);
|
expiryDate = DateUtils.expiryDateAfterDays(issueDate, durationInDays);
|
||||||
}
|
}
|
||||||
|
if (uid == null) {
|
||||||
|
uid = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
return new TrialLicense() {
|
return new TrialLicense() {
|
||||||
@Override
|
@Override
|
||||||
public ESLicenses.FeatureType feature() {
|
public ESLicenses.FeatureType feature() {
|
||||||
|
@ -105,6 +148,16 @@ public class TrialLicensesBuilder {
|
||||||
public long expiryDate() {
|
public long expiryDate() {
|
||||||
return expiryDate;
|
return expiryDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int maxNodes() {
|
||||||
|
return maxNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String uid() {
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +169,8 @@ public class TrialLicensesBuilder {
|
||||||
msg = "issueDate has to be set";
|
msg = "issueDate has to be set";
|
||||||
} else if (durationInDays == -1 && expiryDate == -1) {
|
} else if (durationInDays == -1 && expiryDate == -1) {
|
||||||
msg = "durationInDays or expiryDate has to be set";
|
msg = "durationInDays or expiryDate has to be set";
|
||||||
|
} else if (maxNodes == -1) {
|
||||||
|
msg = "maxNodes has to be set";
|
||||||
}
|
}
|
||||||
if (msg != null) {
|
if (msg != null) {
|
||||||
throw new IllegalArgumentException(msg);
|
throw new IllegalArgumentException(msg);
|
||||||
|
|
Loading…
Reference in New Issue