Refactored api for plugins into it's own module
Original commit: elastic/x-pack-elasticsearch@c3505f6c65
This commit is contained in:
parent
a79557c0bc
commit
c5a74df643
|
@ -0,0 +1 @@
|
||||||
|
/eclipse-build/
|
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>elasticsearch-license</artifactId>
|
||||||
|
<groupId>org.elasticsearch</groupId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>elasticsearch-license-plugin-api</artifactId>
|
||||||
|
<properties>
|
||||||
|
<license.basedir combine.self="override">${project.parent.basedir}</license.basedir>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.elasticsearch</groupId>
|
||||||
|
<artifactId>elasticsearch-license-licensor</artifactId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.elasticsearch</groupId>
|
||||||
|
<artifactId>elasticsearch-license-core</artifactId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<!-- <plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>for-plugin</id>
|
||||||
|
<phase>prepare-package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>-->
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.carrotsearch.randomizedtesting</groupId>
|
||||||
|
<artifactId>junit4-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
* 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.Version;
|
||||||
|
import org.elasticsearch.common.Nullable;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
import org.elasticsearch.license.core.License;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public class LicenseVersion implements Serializable {
|
||||||
|
|
||||||
|
// The logic for ID is: XXYYZZAA, where XX is major version, YY is minor version, ZZ is revision, and AA is Beta/RC indicator
|
||||||
|
// AA values below 50 are beta builds, and below 99 are RC builds, with 99 indicating a release
|
||||||
|
// the (internal) format of the id is there so we can easily do after/before checks on the id
|
||||||
|
|
||||||
|
public static final int V_1_0_0_ID = /*00*/1000099;
|
||||||
|
public static final int V_2_0_0_ID = /*00*/2000099;
|
||||||
|
public static final LicenseVersion V_1_0_0 = new LicenseVersion(V_1_0_0_ID, false, License.VERSION_START, Version.V_1_4_0_Beta1);
|
||||||
|
public static final LicenseVersion V_2_0_0 = new LicenseVersion(V_2_0_0_ID, true, License.VERSION_START, Version.V_2_0_0);
|
||||||
|
|
||||||
|
public static final LicenseVersion CURRENT = V_2_0_0;
|
||||||
|
|
||||||
|
public static LicenseVersion readVersion(StreamInput in) throws IOException {
|
||||||
|
return fromId(in.readVInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LicenseVersion fromId(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case V_1_0_0_ID:
|
||||||
|
return V_1_0_0;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return new LicenseVersion(id, null, License.VERSION_CURRENT, Version.CURRENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeVersion(LicenseVersion version, StreamOutput out) throws IOException {
|
||||||
|
out.writeVInt(version.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the smallest version between the 2.
|
||||||
|
*/
|
||||||
|
public static LicenseVersion smallest(LicenseVersion version1, LicenseVersion version2) {
|
||||||
|
return version1.id < version2.id ? version1 : version2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the version given its string representation, current version if the argument is null or empty
|
||||||
|
*/
|
||||||
|
public static LicenseVersion fromString(String version) {
|
||||||
|
if (!Strings.hasLength(version)) {
|
||||||
|
return LicenseVersion.CURRENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] parts = version.split("\\.");
|
||||||
|
if (parts.length < 3 || parts.length > 4) {
|
||||||
|
throw new IllegalArgumentException("the version needs to contain major, minor and revision, and optionally the build");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//we reverse the version id calculation based on some assumption as we can't reliably reverse the modulo
|
||||||
|
int major = Integer.parseInt(parts[0]) * 1000000;
|
||||||
|
int minor = Integer.parseInt(parts[1]) * 10000;
|
||||||
|
int revision = Integer.parseInt(parts[2]) * 100;
|
||||||
|
|
||||||
|
int build = 99;
|
||||||
|
if (parts.length == 4) {
|
||||||
|
String buildStr = parts[3];
|
||||||
|
if (buildStr.startsWith("Beta")) {
|
||||||
|
build = Integer.parseInt(buildStr.substring(4));
|
||||||
|
}
|
||||||
|
if (buildStr.startsWith("RC")) {
|
||||||
|
build = Integer.parseInt(buildStr.substring(2)) + 50;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fromId(major + minor + revision + build);
|
||||||
|
|
||||||
|
} catch(NumberFormatException e) {
|
||||||
|
throw new IllegalArgumentException("unable to parse version " + version, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int id;
|
||||||
|
public final byte major;
|
||||||
|
public final byte minor;
|
||||||
|
public final byte revision;
|
||||||
|
public final byte build;
|
||||||
|
public final Boolean snapshot;
|
||||||
|
public final int minSignatureVersion;
|
||||||
|
public final Version minEsCompatibilityVersion;
|
||||||
|
|
||||||
|
LicenseVersion(int id, @Nullable Boolean snapshot, int minSignatureVersion, Version minEsCompatibilityVersion) {
|
||||||
|
this.id = id;
|
||||||
|
this.major = (byte) ((id / 1000000) % 100);
|
||||||
|
this.minor = (byte) ((id / 10000) % 100);
|
||||||
|
this.revision = (byte) ((id / 100) % 100);
|
||||||
|
this.build = (byte) (id % 100);
|
||||||
|
this.snapshot = snapshot;
|
||||||
|
this.minSignatureVersion = minSignatureVersion;
|
||||||
|
this.minEsCompatibilityVersion = minEsCompatibilityVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean snapshot() {
|
||||||
|
return snapshot != null && snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean after(LicenseVersion version) {
|
||||||
|
return version.id < id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean before(LicenseVersion version) {
|
||||||
|
return version.id > id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum compatible version based on the current
|
||||||
|
* version. Ie a node needs to have at least the return version in order
|
||||||
|
* to communicate with a node running the current version. The returned version
|
||||||
|
* is in most of the cases the smallest major version release unless the current version
|
||||||
|
* is a beta or RC release then the version itself is returned.
|
||||||
|
*/
|
||||||
|
public LicenseVersion minimumCompatibilityVersion() {
|
||||||
|
return LicenseVersion.smallest(this, fromId(major * 1000000 + 99));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The minimum elasticsearch version this license version is compatible with.
|
||||||
|
*/
|
||||||
|
public Version minimumEsCompatiblityVersion() {
|
||||||
|
return minEsCompatibilityVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The minimum license signature version this license plugin is compatible with.
|
||||||
|
*/
|
||||||
|
public int minimumSignatureVersion() {
|
||||||
|
return minSignatureVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just the version number (without -SNAPSHOT if snapshot).
|
||||||
|
*/
|
||||||
|
public String number() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(major).append('.').append(minor).append('.').append(revision);
|
||||||
|
if (build < 50) {
|
||||||
|
sb.append(".Beta").append(build);
|
||||||
|
} else if (build < 99) {
|
||||||
|
sb.append(".RC").append(build - 50);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append(number());
|
||||||
|
if (snapshot()) {
|
||||||
|
sb.append("-SNAPSHOT");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
LicenseVersion that = (LicenseVersion) o;
|
||||||
|
|
||||||
|
if (id != that.id) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.license.plugin.core;
|
||||||
|
|
||||||
|
import org.elasticsearch.ElasticsearchException;
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception to be thrown when a feature action requires a valid license
|
||||||
|
*/
|
||||||
|
public class LicenseExpiredException extends ElasticsearchException {
|
||||||
|
|
||||||
|
private final String feature;
|
||||||
|
|
||||||
|
public LicenseExpiredException(String feature) {
|
||||||
|
super("license expired for feature [" + feature + "]");
|
||||||
|
this.feature = feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestStatus status() {
|
||||||
|
return RestStatus.UNAUTHORIZED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String feature() {
|
||||||
|
return feature;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||||
|
* or more contributor license agreements. Licensed under the Elastic License;
|
||||||
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
|
*/
|
||||||
|
package org.elasticsearch.license.plugin.core;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.license.core.License;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
|
||||||
|
//@ImplementedBy(LicensesService.class)
|
||||||
|
public interface LicensesClientService {
|
||||||
|
|
||||||
|
public interface Listener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to enable a feature
|
||||||
|
*/
|
||||||
|
public void onEnabled(License license);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to disable a feature
|
||||||
|
*/
|
||||||
|
public void onDisabled(License license);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a feature for licensing
|
||||||
|
*
|
||||||
|
* @param feature - name of the feature to register (must be in sync with license Generator feature name)
|
||||||
|
* @param trialLicenseOptions - Trial license specification used to generate a one-time trial license for the feature;
|
||||||
|
* use <code>null</code> if no trial license should be generated for the feature
|
||||||
|
* @param expirationCallbacks - A collection of Pre and/or Post expiration callbacks
|
||||||
|
* @param listener - used to notify on feature enable/disable
|
||||||
|
*/
|
||||||
|
void register(String feature, TrialLicenseOptions trialLicenseOptions, Collection<ExpirationCallback> expirationCallbacks, Listener listener);
|
||||||
|
|
||||||
|
public static class TrialLicenseOptions {
|
||||||
|
final TimeValue duration;
|
||||||
|
final int maxNodes;
|
||||||
|
|
||||||
|
public TrialLicenseOptions(TimeValue duration, int maxNodes) {
|
||||||
|
this.duration = duration;
|
||||||
|
this.maxNodes = maxNodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static interface LicenseCallback {
|
||||||
|
void on(License license, ExpirationStatus status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class ExpirationCallback implements LicenseCallback {
|
||||||
|
|
||||||
|
public enum Orientation { PRE, POST }
|
||||||
|
|
||||||
|
public static abstract class Pre extends ExpirationCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback schedule prior to license expiry
|
||||||
|
*
|
||||||
|
* @param min latest relative time to execute before license expiry
|
||||||
|
* @param max earliest relative time to execute before license expiry
|
||||||
|
* @param frequency interval between execution
|
||||||
|
*/
|
||||||
|
public Pre(TimeValue min, TimeValue max, TimeValue frequency) {
|
||||||
|
super(Orientation.PRE, min, max, frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(long expirationDate, long now) {
|
||||||
|
long expiryDuration = expirationDate - now;
|
||||||
|
if (expiryDuration > 0l) {
|
||||||
|
if (expiryDuration <= max().getMillis()) {
|
||||||
|
return expiryDuration >= min().getMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static abstract class Post extends ExpirationCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback schedule after license expiry
|
||||||
|
*
|
||||||
|
* @param min earliest relative time to execute after license expiry
|
||||||
|
* @param max latest relative time to execute after license expiry
|
||||||
|
* @param frequency interval between execution
|
||||||
|
*/
|
||||||
|
public Post(TimeValue min, TimeValue max, TimeValue frequency) {
|
||||||
|
super(Orientation.POST, min, max, frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(long expirationDate, long now) {
|
||||||
|
long postExpiryDuration = now - expirationDate;
|
||||||
|
if (postExpiryDuration > 0l) {
|
||||||
|
if (postExpiryDuration <= max().getMillis()) {
|
||||||
|
return postExpiryDuration >= min().getMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Orientation orientation;
|
||||||
|
private final TimeValue min;
|
||||||
|
private final TimeValue max;
|
||||||
|
private final TimeValue frequency;
|
||||||
|
|
||||||
|
private ExpirationCallback(Orientation orientation, TimeValue min, TimeValue max, TimeValue frequency) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
this.min = (min == null) ? TimeValue.timeValueMillis(0) : min;
|
||||||
|
this.max = (max == null) ? TimeValue.timeValueMillis(Long.MAX_VALUE) : max;
|
||||||
|
this.frequency = frequency;
|
||||||
|
if (frequency == null) {
|
||||||
|
throw new IllegalArgumentException("frequency can not be null");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Orientation orientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeValue min() {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeValue max() {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeValue frequency() {
|
||||||
|
return frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean matches(long expirationDate, long now);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ExpirationStatus {
|
||||||
|
private final boolean expired;
|
||||||
|
private final TimeValue time;
|
||||||
|
|
||||||
|
ExpirationStatus(boolean expired, TimeValue time) {
|
||||||
|
this.expired = expired;
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean expired() {
|
||||||
|
return expired;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TimeValue time() {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
/eclipse-build/
|
|
@ -12,7 +12,8 @@
|
||||||
<artifactId>elasticsearch-license-plugin</artifactId>
|
<artifactId>elasticsearch-license-plugin</artifactId>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- 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>
|
||||||
<license.basedir combine.self="override">${project.parent.basedir}</license.basedir>
|
<license.basedir combine.self="override">${project.parent.basedir}</license.basedir>
|
||||||
</properties>
|
</properties>
|
||||||
|
@ -30,6 +31,12 @@
|
||||||
<version>2.0.0-SNAPSHOT</version>
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.elasticsearch</groupId>
|
||||||
|
<artifactId>elasticsearch-license-plugin-api</artifactId>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.license.plugin;
|
||||||
import org.elasticsearch.common.inject.AbstractModule;
|
import org.elasticsearch.common.inject.AbstractModule;
|
||||||
import org.elasticsearch.common.inject.Scopes;
|
import org.elasticsearch.common.inject.Scopes;
|
||||||
import org.elasticsearch.license.core.LicenseVerifier;
|
import org.elasticsearch.license.core.LicenseVerifier;
|
||||||
|
import org.elasticsearch.license.plugin.core.LicensesClientService;
|
||||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||||
|
|
||||||
public class LicenseModule extends AbstractModule {
|
public class LicenseModule extends AbstractModule {
|
||||||
|
@ -15,5 +16,6 @@ public class LicenseModule extends AbstractModule {
|
||||||
protected void configure() {
|
protected void configure() {
|
||||||
bind(LicenseVerifier.class).in(Scopes.SINGLETON);
|
bind(LicenseVerifier.class).in(Scopes.SINGLETON);
|
||||||
bind(LicensesService.class).in(Scopes.SINGLETON);
|
bind(LicensesService.class).in(Scopes.SINGLETON);
|
||||||
|
bind(LicensesClientService.class).to(LicensesService.class).in(Scopes.SINGLETON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,43 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
||||||
* or more contributor license agreements. Licensed under the Elastic License;
|
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
|
||||||
*/
|
|
||||||
package org.elasticsearch.license.plugin.core;
|
|
||||||
|
|
||||||
import org.elasticsearch.common.inject.ImplementedBy;
|
|
||||||
import org.elasticsearch.license.core.License;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import static org.elasticsearch.license.plugin.core.LicensesService.*;
|
|
||||||
import static org.elasticsearch.license.plugin.core.LicensesService.TrialLicenseOptions;
|
|
||||||
|
|
||||||
@ImplementedBy(LicensesService.class)
|
|
||||||
public interface LicensesClientService {
|
|
||||||
|
|
||||||
public interface Listener {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to enable a feature
|
|
||||||
*/
|
|
||||||
public void onEnabled(License license);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called to disable a feature
|
|
||||||
*/
|
|
||||||
public void onDisabled(License license);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers a feature for licensing
|
|
||||||
*
|
|
||||||
* @param feature - name of the feature to register (must be in sync with license Generator feature name)
|
|
||||||
* @param trialLicenseOptions - Trial license specification used to generate a one-time trial license for the feature;
|
|
||||||
* use <code>null</code> if no trial license should be generated for the feature
|
|
||||||
* @param expirationCallbacks - A collection of Pre and/or Post expiration callbacks
|
|
||||||
* @param listener - used to notify on feature enable/disable
|
|
||||||
*/
|
|
||||||
void register(String feature, TrialLicenseOptions trialLicenseOptions, Collection<ExpirationCallback> expirationCallbacks, Listener listener);
|
|
||||||
}
|
|
|
@ -741,125 +741,8 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TrialLicenseOptions {
|
|
||||||
final TimeValue duration;
|
|
||||||
final int maxNodes;
|
|
||||||
|
|
||||||
public TrialLicenseOptions(TimeValue duration, int maxNodes) {
|
|
||||||
this.duration = duration;
|
|
||||||
this.maxNodes = maxNodes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ExpirationStatus {
|
|
||||||
private final boolean expired;
|
|
||||||
private final TimeValue time;
|
|
||||||
|
|
||||||
private ExpirationStatus(boolean expired, TimeValue time) {
|
|
||||||
this.expired = expired;
|
|
||||||
this.time = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean expired() {
|
|
||||||
return expired;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeValue time() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static interface LicenseCallback {
|
|
||||||
void on(License license, ExpirationStatus status);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class ExpirationCallback implements LicenseCallback {
|
|
||||||
|
|
||||||
public enum Orientation { PRE, POST }
|
|
||||||
|
|
||||||
public static abstract class Pre extends ExpirationCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback schedule prior to license expiry
|
|
||||||
*
|
|
||||||
* @param min latest relative time to execute before license expiry
|
|
||||||
* @param max earliest relative time to execute before license expiry
|
|
||||||
* @param frequency interval between execution
|
|
||||||
*/
|
|
||||||
public Pre(TimeValue min, TimeValue max, TimeValue frequency) {
|
|
||||||
super(Orientation.PRE, min, max, frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(long expirationDate, long now) {
|
|
||||||
long expiryDuration = expirationDate - now;
|
|
||||||
if (expiryDuration > 0l) {
|
|
||||||
if (expiryDuration <= max().getMillis()) {
|
|
||||||
return expiryDuration >= min().getMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static abstract class Post extends ExpirationCallback {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback schedule after license expiry
|
|
||||||
*
|
|
||||||
* @param min earliest relative time to execute after license expiry
|
|
||||||
* @param max latest relative time to execute after license expiry
|
|
||||||
* @param frequency interval between execution
|
|
||||||
*/
|
|
||||||
public Post(TimeValue min, TimeValue max, TimeValue frequency) {
|
|
||||||
super(Orientation.POST, min, max, frequency);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean matches(long expirationDate, long now) {
|
|
||||||
long postExpiryDuration = now - expirationDate;
|
|
||||||
if (postExpiryDuration > 0l) {
|
|
||||||
if (postExpiryDuration <= max().getMillis()) {
|
|
||||||
return postExpiryDuration >= min().getMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Orientation orientation;
|
|
||||||
private final TimeValue min;
|
|
||||||
private final TimeValue max;
|
|
||||||
private final TimeValue frequency;
|
|
||||||
|
|
||||||
private ExpirationCallback(Orientation orientation, TimeValue min, TimeValue max, TimeValue frequency) {
|
|
||||||
this.orientation = orientation;
|
|
||||||
this.min = (min == null) ? TimeValue.timeValueMillis(0) : min;
|
|
||||||
this.max = (max == null) ? TimeValue.timeValueMillis(Long.MAX_VALUE) : max;
|
|
||||||
this.frequency = frequency;
|
|
||||||
if (frequency == null) {
|
|
||||||
throw new IllegalArgumentException("frequency can not be null");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Orientation orientation() {
|
|
||||||
return orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeValue min() {
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeValue max() {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
public TimeValue frequency() {
|
|
||||||
return frequency;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract boolean matches(long expirationDate, long now);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores configuration and listener for a feature
|
* Stores configuration and listener for a feature
|
||||||
|
@ -993,6 +876,7 @@ public class LicensesService extends AbstractLifecycleComponent<LicensesService>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "(feature: " + feature + ", enabled: " + enabled + ")";
|
return "(feature: " + feature + ", enabled: " + enabled + ")";
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue