Add max_resource_units to enterprise license (#50910)
The enterprise license type must have "max_resource_units" and may not have "max_nodes". This change adds support for this new field, validation that the field is present if-and-only-if the license is enterprise and bumps the license version number to reflect the new field. Includes a BWC layer to return "max_nodes: ${max_resource_units}" in the GET license API. Backport of: #50735
This commit is contained in:
parent
f0924e6d5b
commit
c2acb8830a
|
@ -113,13 +113,19 @@ public class License implements ToXContentObject {
|
|||
static boolean isTrial(String typeName) {
|
||||
return TRIAL.getTypeName().equals(typeName);
|
||||
}
|
||||
|
||||
static boolean isEnterprise(String typeName) {
|
||||
return ENTERPRISE.getTypeName().equals(typeName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final int VERSION_START = 1;
|
||||
public static final int VERSION_NO_FEATURE_TYPE = 2;
|
||||
public static final int VERSION_START_DATE = 3;
|
||||
public static final int VERSION_CRYPTO_ALGORITHMS = 4;
|
||||
public static final int VERSION_CURRENT = VERSION_CRYPTO_ALGORITHMS;
|
||||
public static final int VERSION_ENTERPRISE = 5;
|
||||
public static final int VERSION_CURRENT = VERSION_ENTERPRISE;
|
||||
|
||||
/**
|
||||
* XContent param name to deserialize license(s) with
|
||||
|
@ -159,13 +165,14 @@ public class License implements ToXContentObject {
|
|||
private final long expiryDate;
|
||||
private final long startDate;
|
||||
private final int maxNodes;
|
||||
private final int maxResourceUnits;
|
||||
private final OperationMode operationMode;
|
||||
|
||||
/**
|
||||
* Decouples operation mode of a license from the license type value.
|
||||
* <p>
|
||||
* Note: The mode indicates features that should be made available, but it does not indicate whether the license is active!
|
||||
*
|
||||
* <p>
|
||||
* The id byte is used for ordering operation modes
|
||||
*/
|
||||
public enum OperationMode {
|
||||
|
@ -182,13 +189,16 @@ public class License implements ToXContentObject {
|
|||
this.id = id;
|
||||
}
|
||||
|
||||
/** Returns non-zero positive number when <code>opMode1</code> is greater than <code>opMode2</code> */
|
||||
/**
|
||||
* Returns non-zero positive number when <code>opMode1</code> is greater than <code>opMode2</code>
|
||||
*/
|
||||
public static int compare(OperationMode opMode1, OperationMode opMode2) {
|
||||
return Integer.compare(opMode1.id, opMode2.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the operating mode for a license type
|
||||
*
|
||||
* @see LicenseType#resolve(License)
|
||||
* @see #parse(String)
|
||||
*/
|
||||
|
@ -217,6 +227,7 @@ public class License implements ToXContentObject {
|
|||
* Parses an {@code OperatingMode} from a String.
|
||||
* The string must name an operating mode, and not a licensing level (that is, it cannot parse old style license levels
|
||||
* such as "dev" or "silver").
|
||||
*
|
||||
* @see #description()
|
||||
*/
|
||||
public static OperationMode parse(String mode) {
|
||||
|
@ -233,8 +244,8 @@ public class License implements ToXContentObject {
|
|||
}
|
||||
}
|
||||
|
||||
private License(int version, String uid, String issuer, String issuedTo, long issueDate, String type,
|
||||
String subscriptionType, String feature, String signature, long expiryDate, int maxNodes, long startDate) {
|
||||
private License(int version, String uid, String issuer, String issuedTo, long issueDate, String type, String subscriptionType,
|
||||
String feature, String signature, long expiryDate, int maxNodes, int maxResourceUnits, long startDate) {
|
||||
this.version = version;
|
||||
this.uid = uid;
|
||||
this.issuer = issuer;
|
||||
|
@ -252,6 +263,7 @@ public class License implements ToXContentObject {
|
|||
this.expiryDate = expiryDate;
|
||||
}
|
||||
this.maxNodes = maxNodes;
|
||||
this.maxResourceUnits = maxResourceUnits;
|
||||
this.startDate = startDate;
|
||||
this.operationMode = OperationMode.resolve(LicenseType.resolve(this));
|
||||
validate();
|
||||
|
@ -300,12 +312,21 @@ public class License implements ToXContentObject {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of nodes this license has been issued for
|
||||
* @return the maximum number of nodes this license has been issued for, or {@code -1} if this license is not node based.
|
||||
*/
|
||||
public int maxNodes() {
|
||||
return maxNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of "resource units" this license has been issued for, or {@code -1} if this license is not resource based.
|
||||
* A "resource unit" is a measure of computing power (RAM/CPU), the definition of which is maintained outside of the license format,
|
||||
* or this class.
|
||||
*/
|
||||
public int maxResourceUnits() {
|
||||
return maxResourceUnits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a string representing the entity this licenses has been issued to
|
||||
*/
|
||||
|
@ -392,20 +413,39 @@ public class License implements ToXContentObject {
|
|||
throw new IllegalStateException("uid can not be null");
|
||||
} else if (feature == null && version == VERSION_START) {
|
||||
throw new IllegalStateException("feature can not be null");
|
||||
} else if (maxNodes == -1) {
|
||||
throw new IllegalStateException("maxNodes has to be set");
|
||||
} else if (expiryDate == -1) {
|
||||
throw new IllegalStateException("expiryDate has to be set");
|
||||
} else if (expiryDate == LicenseService.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS && LicenseType.isBasic(type) == false) {
|
||||
throw new IllegalStateException("only basic licenses are allowed to have no expiration");
|
||||
}
|
||||
|
||||
if (LicenseType.isEnterprise(type) && version < VERSION_ENTERPRISE) {
|
||||
throw new IllegalStateException("license type [" + type + "] is not a valid for version [" + version + "] licenses");
|
||||
}
|
||||
validateLimits(type, maxNodes, maxResourceUnits);
|
||||
}
|
||||
|
||||
private static void validateLimits(String type, int maxNodes, int maxResourceUnits) {
|
||||
if (LicenseType.isEnterprise(type)) {
|
||||
if (maxResourceUnits == -1) {
|
||||
throw new IllegalStateException("maxResourceUnits must be set for enterprise licenses (type=[" + type + "])");
|
||||
} else if (maxNodes != -1) {
|
||||
throw new IllegalStateException("maxNodes may not be set for enterprise licenses (type=[" + type + "])");
|
||||
}
|
||||
} else {
|
||||
if (maxNodes == -1) {
|
||||
throw new IllegalStateException("maxNodes has to be set");
|
||||
} else if (maxResourceUnits != -1) {
|
||||
throw new IllegalStateException("maxResourceUnits may only be set for enterprise licenses (not permitted for type=[" +
|
||||
type + "])");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static License readLicense(StreamInput in) throws IOException {
|
||||
int version = in.readVInt(); // Version for future extensibility
|
||||
if (version > VERSION_CURRENT) {
|
||||
throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest elasticsearch-license" +
|
||||
" plugin");
|
||||
throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest elasticsearch release");
|
||||
}
|
||||
Builder builder = builder();
|
||||
builder.version(version);
|
||||
|
@ -420,6 +460,9 @@ public class License implements ToXContentObject {
|
|||
}
|
||||
builder.expiryDate(in.readLong());
|
||||
builder.maxNodes(in.readInt());
|
||||
if (version >= VERSION_ENTERPRISE) {
|
||||
builder.maxResourceUnits(in.readInt());
|
||||
}
|
||||
builder.issuedTo(in.readString());
|
||||
builder.issuer(in.readString());
|
||||
builder.signature(in.readOptionalString());
|
||||
|
@ -442,6 +485,9 @@ public class License implements ToXContentObject {
|
|||
}
|
||||
out.writeLong(expiryDate);
|
||||
out.writeInt(maxNodes);
|
||||
if (version >= VERSION_ENTERPRISE) {
|
||||
out.writeInt(maxResourceUnits);
|
||||
}
|
||||
out.writeString(issuedTo);
|
||||
out.writeString(issuer);
|
||||
out.writeOptionalString(signature);
|
||||
|
@ -506,7 +552,16 @@ public class License implements ToXContentObject {
|
|||
if (expiryDate != LicenseService.BASIC_SELF_GENERATED_LICENSE_EXPIRATION_MILLIS) {
|
||||
builder.timeField(Fields.EXPIRY_DATE_IN_MILLIS, Fields.EXPIRY_DATE, expiryDate);
|
||||
}
|
||||
builder.field(Fields.MAX_NODES, maxNodes);
|
||||
|
||||
if (version >= VERSION_ENTERPRISE) {
|
||||
builder.field(Fields.MAX_NODES, maxNodes == -1 ? null : maxNodes);
|
||||
builder.field(Fields.MAX_RESOURCE_UNITS, maxResourceUnits == -1 ? null : maxResourceUnits);
|
||||
} else if (hideEnterprise && maxNodes == -1) {
|
||||
builder.field(Fields.MAX_NODES, maxResourceUnits);
|
||||
} else {
|
||||
builder.field(Fields.MAX_NODES, maxNodes);
|
||||
}
|
||||
|
||||
builder.field(Fields.ISSUED_TO, issuedTo);
|
||||
builder.field(Fields.ISSUER, issuer);
|
||||
if (!licenseSpecMode && !restViewMode && signature != null) {
|
||||
|
@ -551,6 +606,8 @@ public class License implements ToXContentObject {
|
|||
builder.startDate(parser.longValue());
|
||||
} else if (Fields.MAX_NODES.equals(currentFieldName)) {
|
||||
builder.maxNodes(parser.intValue());
|
||||
} else if (Fields.MAX_RESOURCE_UNITS.equals(currentFieldName)) {
|
||||
builder.maxResourceUnits(parser.intValue());
|
||||
} else if (Fields.ISSUED_TO.equals(currentFieldName)) {
|
||||
builder.issuedTo(parser.text());
|
||||
} else if (Fields.ISSUER.equals(currentFieldName)) {
|
||||
|
@ -593,7 +650,7 @@ public class License implements ToXContentObject {
|
|||
throw new ElasticsearchException("malformed signature for license [" + builder.uid + "]");
|
||||
} else if (version > VERSION_CURRENT) {
|
||||
throw new ElasticsearchException("Unknown license version found, please upgrade all nodes to the latest " +
|
||||
"elasticsearch-license plugin");
|
||||
"elasticsearch-license plugin");
|
||||
}
|
||||
// signature version is the source of truth
|
||||
builder.version(version);
|
||||
|
@ -625,8 +682,7 @@ public class License implements ToXContentObject {
|
|||
// EMPTY is safe here because we don't call namedObject
|
||||
try (InputStream byteStream = bytes.streamInput();
|
||||
XContentParser parser = xContentType.xContent()
|
||||
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, byteStream))
|
||||
{
|
||||
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, byteStream)) {
|
||||
License license = null;
|
||||
if (parser.nextToken() == XContentParser.Token.START_OBJECT) {
|
||||
if (parser.nextToken() == XContentParser.Token.FIELD_NAME) {
|
||||
|
@ -675,7 +731,7 @@ public class License implements ToXContentObject {
|
|||
|
||||
if (issueDate != license.issueDate) return false;
|
||||
if (expiryDate != license.expiryDate) return false;
|
||||
if (startDate!= license.startDate) return false;
|
||||
if (startDate != license.startDate) return false;
|
||||
if (maxNodes != license.maxNodes) return false;
|
||||
if (version != license.version) return false;
|
||||
if (uid != null ? !uid.equals(license.uid) : license.uid != null) return false;
|
||||
|
@ -700,7 +756,7 @@ public class License implements ToXContentObject {
|
|||
result = 31 * result + (feature != null ? feature.hashCode() : 0);
|
||||
result = 31 * result + (signature != null ? signature.hashCode() : 0);
|
||||
result = 31 * result + (int) (expiryDate ^ (expiryDate >>> 32));
|
||||
result = 31 * result + (int) (startDate ^ (startDate>>> 32));
|
||||
result = 31 * result + (int) (startDate ^ (startDate >>> 32));
|
||||
result = 31 * result + maxNodes;
|
||||
result = 31 * result + version;
|
||||
return result;
|
||||
|
@ -719,6 +775,7 @@ public class License implements ToXContentObject {
|
|||
public static final String START_DATE_IN_MILLIS = "start_date_in_millis";
|
||||
public static final String START_DATE = "start_date";
|
||||
public static final String MAX_NODES = "max_nodes";
|
||||
public static final String MAX_RESOURCE_UNITS = "max_resource_units";
|
||||
public static final String ISSUED_TO = "issued_to";
|
||||
public static final String ISSUER = "issuer";
|
||||
public static final String VERSION = "version";
|
||||
|
@ -762,6 +819,7 @@ public class License implements ToXContentObject {
|
|||
private long expiryDate = -1;
|
||||
private long startDate = -1;
|
||||
private int maxNodes = -1;
|
||||
private int maxResourceUnits = -1;
|
||||
|
||||
public Builder uid(String uid) {
|
||||
this.uid = uid;
|
||||
|
@ -817,6 +875,11 @@ public class License implements ToXContentObject {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder maxResourceUnits(int maxUnits) {
|
||||
this.maxResourceUnits = maxUnits;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder signature(String signature) {
|
||||
if (signature != null) {
|
||||
this.signature = signature;
|
||||
|
@ -831,17 +894,18 @@ public class License implements ToXContentObject {
|
|||
|
||||
public Builder fromLicenseSpec(License license, String signature) {
|
||||
return uid(license.uid())
|
||||
.version(license.version())
|
||||
.issuedTo(license.issuedTo())
|
||||
.issueDate(license.issueDate())
|
||||
.startDate(license.startDate())
|
||||
.type(license.type())
|
||||
.subscriptionType(license.subscriptionType)
|
||||
.feature(license.feature)
|
||||
.maxNodes(license.maxNodes())
|
||||
.expiryDate(license.expiryDate())
|
||||
.issuer(license.issuer())
|
||||
.signature(signature);
|
||||
.version(license.version())
|
||||
.issuedTo(license.issuedTo())
|
||||
.issueDate(license.issueDate())
|
||||
.startDate(license.startDate())
|
||||
.type(license.type())
|
||||
.subscriptionType(license.subscriptionType)
|
||||
.feature(license.feature)
|
||||
.maxNodes(license.maxNodes())
|
||||
.maxResourceUnits(license.maxResourceUnits())
|
||||
.expiryDate(license.expiryDate())
|
||||
.issuer(license.issuer())
|
||||
.signature(signature);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -850,15 +914,15 @@ public class License implements ToXContentObject {
|
|||
*/
|
||||
public Builder fromPre20LicenseSpec(License pre20License) {
|
||||
return uid(pre20License.uid())
|
||||
.issuedTo(pre20License.issuedTo())
|
||||
.issueDate(pre20License.issueDate())
|
||||
.maxNodes(pre20License.maxNodes())
|
||||
.expiryDate(pre20License.expiryDate());
|
||||
.issuedTo(pre20License.issuedTo())
|
||||
.issueDate(pre20License.issueDate())
|
||||
.maxNodes(pre20License.maxNodes())
|
||||
.expiryDate(pre20License.expiryDate());
|
||||
}
|
||||
|
||||
public License build() {
|
||||
return new License(version, uid, issuer, issuedTo, issueDate, type,
|
||||
subscriptionType, feature, signature, expiryDate, maxNodes, startDate);
|
||||
subscriptionType, feature, signature, expiryDate, maxNodes, maxResourceUnits, startDate);
|
||||
}
|
||||
|
||||
public Builder validate() {
|
||||
|
@ -874,11 +938,10 @@ public class License implements ToXContentObject {
|
|||
throw new IllegalStateException("uid can not be null");
|
||||
} else if (signature == null) {
|
||||
throw new IllegalStateException("signature can not be null");
|
||||
} else if (maxNodes == -1) {
|
||||
throw new IllegalStateException("maxNodes has to be set");
|
||||
} else if (expiryDate == -1) {
|
||||
throw new IllegalStateException("expiryDate has to be set");
|
||||
}
|
||||
validateLimits(type, maxNodes, maxResourceUnits);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,7 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
* Max number of nodes licensed by generated trial license
|
||||
*/
|
||||
static final int SELF_GENERATED_LICENSE_MAX_NODES = 1000;
|
||||
static final int SELF_GENERATED_LICENSE_MAX_RESOURCE_UNITS = SELF_GENERATED_LICENSE_MAX_NODES;
|
||||
|
||||
public static final String LICENSE_JOB = "licenseJob";
|
||||
|
||||
|
@ -292,11 +293,8 @@ public class LicenseService extends AbstractLifecycleComponent implements Cluste
|
|||
}
|
||||
|
||||
private static boolean licenseIsCompatible(License license, Version version) {
|
||||
if (License.LicenseType.ENTERPRISE.getTypeName().equalsIgnoreCase(license.type())) {
|
||||
return version.onOrAfter(Version.V_7_6_0);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
final int maxVersion = LicenseUtils.getMaxLicenseVersion(version);
|
||||
return license.version() <= maxVersion;
|
||||
}
|
||||
|
||||
private boolean isAllowedLicenseType(License.LicenseType type) {
|
||||
|
|
|
@ -11,8 +11,6 @@ import org.elasticsearch.cluster.node.DiscoveryNodes;
|
|||
import org.elasticsearch.license.License.LicenseType;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class LicenseUtils {
|
||||
|
||||
public static final String EXPIRED_FEATURE_METADATA = "es.license.expired.feature";
|
||||
|
@ -49,25 +47,30 @@ public class LicenseUtils {
|
|||
* recreated with the new key
|
||||
*/
|
||||
public static boolean signatureNeedsUpdate(License license, DiscoveryNodes currentNodes) {
|
||||
assert License.VERSION_CRYPTO_ALGORITHMS == License.VERSION_CURRENT : "update this method when adding a new version";
|
||||
assert License.VERSION_ENTERPRISE == License.VERSION_CURRENT : "update this method when adding a new version";
|
||||
|
||||
String typeName = license.type();
|
||||
return (LicenseType.isBasic(typeName) || LicenseType.isTrial(typeName)) &&
|
||||
// only upgrade signature when all nodes are ready to deserialize the new signature
|
||||
(license.version() < License.VERSION_CRYPTO_ALGORITHMS &&
|
||||
compatibleLicenseVersion(currentNodes) == License.VERSION_CRYPTO_ALGORITHMS
|
||||
compatibleLicenseVersion(currentNodes) >= License.VERSION_CRYPTO_ALGORITHMS
|
||||
);
|
||||
}
|
||||
|
||||
public static int compatibleLicenseVersion(DiscoveryNodes currentNodes) {
|
||||
assert License.VERSION_CRYPTO_ALGORITHMS == License.VERSION_CURRENT : "update this method when adding a new version";
|
||||
|
||||
if (StreamSupport.stream(currentNodes.spliterator(), false)
|
||||
.allMatch(node -> node.getVersion().onOrAfter(Version.V_6_4_0))) {
|
||||
// License.VERSION_CRYPTO_ALGORITHMS was introduced in 6.4.0
|
||||
return License.VERSION_CRYPTO_ALGORITHMS;
|
||||
} else {
|
||||
return License.VERSION_START_DATE;
|
||||
}
|
||||
return getMaxLicenseVersion(currentNodes.getMinNodeVersion());
|
||||
}
|
||||
|
||||
public static int getMaxLicenseVersion(Version version){
|
||||
if (version != null) {
|
||||
if (version.before(Version.V_6_4_0)) {
|
||||
return License.VERSION_START_DATE;
|
||||
}
|
||||
if (version.before(Version.V_7_6_0)) {
|
||||
return License.VERSION_CRYPTO_ALGORITHMS;
|
||||
}
|
||||
}
|
||||
assert License.VERSION_ENTERPRISE == License.VERSION_CURRENT : "update this method when adding a new version";
|
||||
return License.VERSION_ENTERPRISE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,12 +51,13 @@ public class RestGetLicenseAction extends XPackRestHandler {
|
|||
*/
|
||||
@Override
|
||||
public RestChannelConsumer doPrepareRequest(final RestRequest request, final XPackClient client) throws IOException {
|
||||
final Map<String, String> overrideParams = new HashMap<>(3);
|
||||
overrideParams.put(License.REST_VIEW_MODE, "true");
|
||||
overrideParams.put(License.LICENSE_VERSION_MODE, String.valueOf(License.VERSION_CURRENT));
|
||||
|
||||
// Hide enterprise licenses by default, there is an opt-in flag to show them
|
||||
final boolean hideEnterprise = request.paramAsBoolean("accept_enterprise", false) == false;
|
||||
final int licenseVersion = hideEnterprise ? License.VERSION_CRYPTO_ALGORITHMS : License.VERSION_CURRENT;
|
||||
|
||||
final Map<String, String> overrideParams = new HashMap<>(3);
|
||||
overrideParams.put(License.REST_VIEW_MODE, "true");
|
||||
overrideParams.put(License.LICENSE_VERSION_MODE, String.valueOf(licenseVersion));
|
||||
overrideParams.put(License.XCONTENT_HIDE_ENTERPRISE, String.valueOf(hideEnterprise));
|
||||
|
||||
final ToXContent.Params params = new ToXContent.DelegatingMapParams(overrideParams, request);
|
||||
|
|
|
@ -75,10 +75,14 @@ public class StartTrialClusterTask extends ClusterStateUpdateTask {
|
|||
License.Builder specBuilder = License.builder()
|
||||
.uid(UUID.randomUUID().toString())
|
||||
.issuedTo(clusterName)
|
||||
.maxNodes(LicenseService.SELF_GENERATED_LICENSE_MAX_NODES)
|
||||
.issueDate(issueDate)
|
||||
.type(request.getType())
|
||||
.expiryDate(expiryDate);
|
||||
if (License.LicenseType.isEnterprise(request.getType())) {
|
||||
specBuilder.maxResourceUnits(LicenseService.SELF_GENERATED_LICENSE_MAX_RESOURCE_UNITS);
|
||||
} else {
|
||||
specBuilder.maxNodes(LicenseService.SELF_GENERATED_LICENSE_MAX_NODES);
|
||||
}
|
||||
License selfGeneratedLicense = SelfGeneratedLicense.create(specBuilder, currentState.nodes());
|
||||
LicensesMetaData newLicensesMetaData = new LicensesMetaData(selfGeneratedLicense, Version.CURRENT);
|
||||
mdBuilder.putCustom(LicensesMetaData.TYPE, newLicensesMetaData);
|
||||
|
|
|
@ -70,6 +70,7 @@ public abstract class AbstractLicenseServiceTestCase extends ESTestCase {
|
|||
when(discoveryNodes.getMasterNode()).thenReturn(mockNode);
|
||||
when(discoveryNodes.spliterator()).thenReturn(Arrays.asList(mockNode).spliterator());
|
||||
when(discoveryNodes.isLocalNodeElectedMaster()).thenReturn(false);
|
||||
when(discoveryNodes.getMinNodeVersion()).thenReturn(mockNode.getVersion());
|
||||
when(state.nodes()).thenReturn(discoveryNodes);
|
||||
when(state.getNodes()).thenReturn(discoveryNodes); // it is really ridiculous we have nodes() and getNodes()...
|
||||
when(clusterService.state()).thenReturn(state);
|
||||
|
|
|
@ -35,15 +35,19 @@ public class LicenseOperationModeUpdateTests extends ESTestCase {
|
|||
|
||||
public void testLicenseOperationModeUpdate() throws Exception {
|
||||
License.LicenseType type = randomFrom(License.LicenseType.values());
|
||||
License license = License.builder()
|
||||
.uid("id")
|
||||
.expiryDate(0)
|
||||
.issueDate(0)
|
||||
.issuedTo("elasticsearch")
|
||||
.issuer("issuer")
|
||||
.type(type)
|
||||
.maxNodes(1)
|
||||
.build();
|
||||
final License.Builder licenseBuilder = License.builder()
|
||||
.uid("id")
|
||||
.expiryDate(0)
|
||||
.issueDate(0)
|
||||
.issuedTo("elasticsearch")
|
||||
.issuer("issuer")
|
||||
.type(type);
|
||||
if (type == License.LicenseType.ENTERPRISE) {
|
||||
licenseBuilder.maxResourceUnits(1);
|
||||
} else {
|
||||
licenseBuilder.maxNodes(1);
|
||||
}
|
||||
License license = licenseBuilder.build();
|
||||
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.resolve(type)));
|
||||
OperationModeFileWatcherTests.writeMode("gold", licenseModeFile);
|
||||
|
|
|
@ -190,7 +190,8 @@ public class LicenseServiceTests extends ESTestCase {
|
|||
.issuer(randomAlphaOfLengthBetween(5, 60))
|
||||
.issuedTo(randomAlphaOfLengthBetween(5, 60))
|
||||
.issueDate(System.currentTimeMillis() - TimeUnit.MINUTES.toMillis(randomLongBetween(1, 5000)))
|
||||
.maxNodes(randomIntBetween(1, 500))
|
||||
.maxNodes(type == License.LicenseType.ENTERPRISE ? -1 : randomIntBetween(1, 500))
|
||||
.maxResourceUnits(type == License.LicenseType.ENTERPRISE ? randomIntBetween(10, 500) : -1)
|
||||
.signature(null)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -6,13 +6,18 @@
|
|||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.UUIDs;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.TestMatchers;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -27,7 +32,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
|
||||
public class LicenseTests extends ESTestCase {
|
||||
|
||||
public void testFromXContent() throws Exception {
|
||||
public void testFromXContentForGoldLicenseWithVersion2Signature() throws Exception {
|
||||
String licenseString = "{\"license\":" +
|
||||
"{\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||
"\"type\":\"gold\"," +
|
||||
|
@ -51,27 +56,107 @@ public class LicenseTests extends ESTestCase {
|
|||
assertThat(license.issuedTo(), equalTo("customer"));
|
||||
assertThat(license.expiryDate(), equalTo(1546596340459L));
|
||||
assertThat(license.issueDate(), equalTo(1546589020459L));
|
||||
assertThat(license.maxNodes(), equalTo(5));
|
||||
assertThat(license.maxResourceUnits(), equalTo(-1));
|
||||
assertThat(license.version(), equalTo(2));
|
||||
}
|
||||
|
||||
public void testFromXContentForGoldLicenseWithVersion4Signature() throws Exception {
|
||||
String licenseString = "{\"license\":{" +
|
||||
"\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||
"\"type\":\"gold\"," +
|
||||
"\"issue_date_in_millis\":1546589020459," +
|
||||
"\"expiry_date_in_millis\":1546596340459," +
|
||||
"\"max_nodes\":5," +
|
||||
"\"issued_to\":\"customer\"," +
|
||||
"\"issuer\":\"elasticsearch\"," +
|
||||
"\"signature\":\"AAAABAAAAA22vXffI41oM4jLCwZ6AAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAH3oL4weubwYGjLGNZsz90" +
|
||||
"EerX6yOX3Dh6wswG9EfqCiyv6lcjuC7aeKKuOkqhMRTHZ9vHnfMuakHWVlpuGC14WyGqaMwSmgTZ9jVAzt/W3sIotRxM/3rtlCXUc1rOUXNFcii1i3Kkrc" +
|
||||
"kTzhENTKjdkOmUN3qZlTEmHkp93eYpx8++iIukHYU9K9Vm2VKgydFfxvYaN/Qr+iPfJSbHJB8+DmS2ywdrmdqW+ScE+1ZNouPNhnP3RKTleNvixXPG9l5B" +
|
||||
"qZ2So1IlCrxVDByA1E6JH5AvjbOucpcGiWCm7IzvfpkzphKHMyxhUaIByoHl9UAf4AdPLhowWAQk0eHMRDDlo=\"," +
|
||||
"\"start_date_in_millis\":-1}}\n";
|
||||
License license = License.fromSource(new BytesArray(licenseString.getBytes(StandardCharsets.UTF_8)),
|
||||
XContentType.JSON);
|
||||
assertThat(license.type(), equalTo("gold"));
|
||||
assertThat(license.uid(), equalTo("4056779d-b823-4c12-a9cb-efa4a8d8c422"));
|
||||
assertThat(license.issuer(), equalTo("elasticsearch"));
|
||||
assertThat(license.issuedTo(), equalTo("customer"));
|
||||
assertThat(license.expiryDate(), equalTo(1546596340459L));
|
||||
assertThat(license.issueDate(), equalTo(1546589020459L));
|
||||
assertThat(license.maxNodes(), equalTo(5));
|
||||
assertThat(license.maxResourceUnits(), equalTo(-1));
|
||||
assertThat(license.version(), equalTo(4));
|
||||
}
|
||||
|
||||
public void testFromXContentForEnterpriseLicenseWithV5Signature() throws Exception {
|
||||
String licenseString = "{\"license\":{" +
|
||||
"\"uid\":\"4056779d-b823-4c12-a9cb-efa4a8d8c422\"," +
|
||||
"\"type\":\"enterprise\"," +
|
||||
"\"issue_date_in_millis\":1546589020459," +
|
||||
"\"expiry_date_in_millis\":1546596340459," +
|
||||
"\"max_nodes\":null," +
|
||||
"\"max_resource_units\":15," +
|
||||
"\"issued_to\":\"customer\"," +
|
||||
"\"issuer\":\"elasticsearch\"," +
|
||||
"\"signature\":\"AAAABQAAAA2MUoEqXb9K9Ie5d6JJAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAAAwVZKGAmDELUlS5PScBkhQsZa" +
|
||||
"DaQTtJ4ZP5EnZ/nLpmCt9Dj7d/FRsgMtHmSJLrr2CdrIo4Vx5VuhmbwzZvXMttLz2lrJzG7770PX3TnC9e7F9GdnE9ec0FP2U0ZlLOBOtPuirX0q+j6GfB+DLyE" +
|
||||
"5D+Lo1NQ3eLJGvbd3DBYPWJxkb+EBVHczCH2OrIEVWnN/TafmkdZCPX5PcultkNOs3j7d3s7b51EXHKoye8UTcB/RGmzZwMah+E6I/VJkqu7UHL8bB01wJeqo6W" +
|
||||
"xI4LC/9+f5kpmHrUu3CHe5pHbmMGDk7O6/cwt1pw/hnJXKIFCi36IGaKcHLgORxQdN0uzE=\"," +
|
||||
"\"start_date_in_millis\":-1}}";
|
||||
License license = License.fromSource(new BytesArray(licenseString.getBytes(StandardCharsets.UTF_8)),
|
||||
XContentType.JSON);
|
||||
assertThat(license.type(), equalTo("enterprise"));
|
||||
assertThat(license.uid(), equalTo("4056779d-b823-4c12-a9cb-efa4a8d8c422"));
|
||||
assertThat(license.issuer(), equalTo("elasticsearch"));
|
||||
assertThat(license.issuedTo(), equalTo("customer"));
|
||||
assertThat(license.expiryDate(), equalTo(1546596340459L));
|
||||
assertThat(license.issueDate(), equalTo(1546589020459L));
|
||||
assertThat(license.maxNodes(), equalTo(-1));
|
||||
assertThat(license.maxResourceUnits(), equalTo(15));
|
||||
assertThat(license.version(), equalTo(5));
|
||||
}
|
||||
|
||||
public void testThatEnterpriseLicenseMayNotHaveMaxNodes() throws Exception {
|
||||
License.Builder builder = randomLicense(License.LicenseType.ENTERPRISE)
|
||||
.maxNodes(randomIntBetween(1, 50))
|
||||
.maxResourceUnits(randomIntBetween(10, 500));
|
||||
final IllegalStateException ex = expectThrows(IllegalStateException.class, builder::build);
|
||||
assertThat(ex, TestMatchers.throwableWithMessage("maxNodes may not be set for enterprise licenses (type=[enterprise])"));
|
||||
}
|
||||
|
||||
public void testThatEnterpriseLicenseMustHaveMaxResourceUnits() throws Exception {
|
||||
License.Builder builder = randomLicense(License.LicenseType.ENTERPRISE)
|
||||
.maxResourceUnits(-1);
|
||||
final IllegalStateException ex = expectThrows(IllegalStateException.class, builder::build);
|
||||
assertThat(ex, TestMatchers.throwableWithMessage("maxResourceUnits must be set for enterprise licenses (type=[enterprise])"));
|
||||
}
|
||||
|
||||
public void testThatRegularLicensesMustHaveMaxNodes() throws Exception {
|
||||
License.LicenseType type = randomValueOtherThan(License.LicenseType.ENTERPRISE, () -> randomFrom(License.LicenseType.values()));
|
||||
License.Builder builder = randomLicense(type)
|
||||
.maxNodes(-1);
|
||||
final IllegalStateException ex = expectThrows(IllegalStateException.class, builder::build);
|
||||
assertThat(ex, TestMatchers.throwableWithMessage("maxNodes has to be set"));
|
||||
}
|
||||
|
||||
public void testThatRegularLicensesMayNotHaveMaxResourceUnits() throws Exception {
|
||||
License.LicenseType type = randomValueOtherThan(License.LicenseType.ENTERPRISE, () -> randomFrom(License.LicenseType.values()));
|
||||
License.Builder builder = randomLicense(type)
|
||||
.maxResourceUnits(randomIntBetween(10, 500))
|
||||
.maxNodes(randomIntBetween(1, 50));
|
||||
final IllegalStateException ex = expectThrows(IllegalStateException.class, builder::build);
|
||||
assertThat(ex, TestMatchers.throwableWithMessage("maxResourceUnits may only be set for enterprise licenses (not permitted " +
|
||||
"for type=[" + type.getTypeName() + "])"));
|
||||
}
|
||||
|
||||
public void testLicenseToAndFromXContentForEveryLicenseType() throws Exception {
|
||||
for (License.LicenseType type : License.LicenseType.values()) {
|
||||
final License license1 = License.builder()
|
||||
.uid(UUIDs.randomBase64UUID(random()))
|
||||
.type(type)
|
||||
.issueDate(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(randomIntBetween(1, 10)))
|
||||
.expiryDate(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(randomIntBetween(1, 1000)))
|
||||
.maxNodes(randomIntBetween(1, 100))
|
||||
.issuedTo(randomAlphaOfLengthBetween(5, 50))
|
||||
.issuer(randomAlphaOfLengthBetween(5, 50))
|
||||
final License license1 = randomLicense(type)
|
||||
// We need a signature that parses correctly, but it doesn't need to verify
|
||||
.signature("AAAAAgAAAA34V2kfTJVtvdL2LttwAAABmFJ6NGRnbEM3WVQrZVQwNkdKQmR1VytlMTMyM1J0dTZ1WGwyY2ZCVFhqMGtJU2gzZ3pnNTVpOW" +
|
||||
"F5Y1NaUkwyN2VsTEtCYnlZR2c5WWtjQ0phaDlhRjlDUXViUmUwMWhjSkE2TFcwSGdneTJHbUV4N2RHUWJxV20ybjRsZHRzV2xkN0ZmdDlYblJmNVc" +
|
||||
"xMlBWeU81V1hLUm1EK0V1dmF3cFdlSGZzTU5SZE1qUmFra3JkS1hCanBWVmVTaFFwV3BVZERzeG9Sci9rYnlJK2toODZXY09tNmFHUVNUL3IyUHEx" +
|
||||
"V3VSTlBneWNJcFQ0bXl0cmhNNnRwbE1CWE4zWjJ5eGFuWFo0NGhsb3B5WFd1eTdYbFFWQkxFVFFPSlBERlB0eVVJYXVSZ0lsR2JpRS9rN1h4MSsvN" +
|
||||
"UpOcGN6cU1NOHN1cHNtSTFIUGN1bWNGNEcxekhrblhNOXZ2VEQvYmRzQUFwbytUZEpRR3l6QU5oS2ZFSFdSbGxxNDZyZ0xvUHIwRjdBL2JqcnJnNG" +
|
||||
"FlK09Cek9pYlJ5Umc9PQAAAQAth77fQLF7CCEL7wA6Z0/UuRm/weECcsjW/50kBnPLO8yEs+9/bPa5LSU0bF6byEXOVeO0ebUQfztpjulbXh8TrBD" +
|
||||
"SG+6VdxGtohPo2IYPBaXzGs3LOOor6An/lhptxBWdwYmfbcp0m8mnXZh1vN9rmbTsZXnhBIoPTaRDwUBi3vJ3Ms3iLaEm4S8Slrfmtht2jUjgGZ2v" +
|
||||
"AeZ9OHU2YsGtrSpz6f")
|
||||
.signature("AAAABQAAAA2MUoEqXb9K9Ie5d6JJAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAAAwVZKGAmDELUlS5PScBkhQsZa" +
|
||||
"DaQTtJ4ZP5EnZ/nLpmCt9Dj7d/FRsgMtHmSJLrr2CdrIo4Vx5VuhmbwzZvXMttLz2lrJzG7770PX3TnC9e7F9GdnE9ec0FP2U0ZlLOBOtPuirX0q+j" +
|
||||
"6GfB+DLyE5D+Lo1NQ3eLJGvbd3DBYPWJxkb+EBVHczCH2OrIEVWnN/TafmkdZCPX5PcultkNOs3j7d3s7b51EXHKoye8UTcB/RGmzZwMah+E6I/VJk" +
|
||||
"qu7UHL8bB01wJeqo6WxI4LC/9+f5kpmHrUu3CHe5pHbmMGDk7O6/cwt1pw/hnJXKIFCi36IGaKcHLgORxQdN0uzE=")
|
||||
.build();
|
||||
XContentParser parser = XContentType.JSON.xContent().createParser(NamedXContentRegistry.EMPTY, THROW_UNSUPPORTED_OPERATION,
|
||||
Strings.toString(license1));
|
||||
|
@ -83,6 +168,46 @@ public class LicenseTests extends ESTestCase {
|
|||
assertThat(license2.issuedTo(), equalTo(license1.issuedTo()));
|
||||
assertThat(license2.expiryDate(), equalTo(license1.expiryDate()));
|
||||
assertThat(license2.issueDate(), equalTo(license1.issueDate()));
|
||||
assertThat(license2.maxNodes(), equalTo(license1.maxNodes()));
|
||||
assertThat(license2.maxResourceUnits(), equalTo(license1.maxResourceUnits()));
|
||||
}
|
||||
}
|
||||
|
||||
public void testSerializationOfLicenseForEveryLicenseType() throws Exception {
|
||||
for (License.LicenseType type : License.LicenseType.values()) {
|
||||
final String signature = randomBoolean() ? null : "AAAABQAAAA2MUoEqXb9K9Ie5d6JJAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEM" +
|
||||
"hm4jAAABAAAwVZKGAmDELUlS5PScBkhQsZaDaQTtJ4ZP5EnZ/nLpmCt9Dj7d/FRsgMtHmSJLrr2CdrIo4Vx5VuhmbwzZvXMttLz2lrJzG7770PX3TnC9e7" +
|
||||
"F9GdnE9ec0FP2U0ZlLOBOtPuirX0q+j6GfB+DLyE5D+Lo1NQ3eLJGvbd3DBYPWJxkb+EBVHczCH2OrIEVWnN/TafmkdZCPX5PcultkNOs3j7d3s7b51EXH" +
|
||||
"Koye8UTcB/RGmzZwMah+E6I/VJkqu7UHL8bB01wJeqo6WxI4LC/9+f5kpmHrUu3CHe5pHbmMGDk7O6/cwt1pw/hnJXKIFCi36IGaKcHLgORxQdN0uzE=";
|
||||
final int version;
|
||||
if (type == License.LicenseType.ENTERPRISE) {
|
||||
version = randomIntBetween(License.VERSION_ENTERPRISE, License.VERSION_CURRENT);
|
||||
} else {
|
||||
version = randomIntBetween(License.VERSION_NO_FEATURE_TYPE, License.VERSION_CURRENT);
|
||||
}
|
||||
|
||||
final License license1 = randomLicense(type).signature(signature).version(version).build();
|
||||
|
||||
final BytesStreamOutput out = new BytesStreamOutput();
|
||||
out.setVersion(Version.CURRENT);
|
||||
license1.writeTo(out);
|
||||
|
||||
final StreamInput in = out.bytes().streamInput();
|
||||
in.setVersion(Version.CURRENT);
|
||||
final License license2 = License.readLicense(in);
|
||||
assertThat(in.read(), Matchers.equalTo(-1));
|
||||
|
||||
assertThat(license2, notNullValue());
|
||||
assertThat(license2.type(), equalTo(type.getTypeName()));
|
||||
assertThat(license2.version(), equalTo(version));
|
||||
assertThat(license2.signature(), equalTo(signature));
|
||||
assertThat(license2.uid(), equalTo(license1.uid()));
|
||||
assertThat(license2.issuer(), equalTo(license1.issuer()));
|
||||
assertThat(license2.issuedTo(), equalTo(license1.issuedTo()));
|
||||
assertThat(license2.expiryDate(), equalTo(license1.expiryDate()));
|
||||
assertThat(license2.issueDate(), equalTo(license1.issueDate()));
|
||||
assertThat(license2.maxNodes(), equalTo(license1.maxNodes()));
|
||||
assertThat(license2.maxResourceUnits(), equalTo(license1.maxResourceUnits()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -158,4 +283,17 @@ public class LicenseTests extends ESTestCase {
|
|||
assertThat(exception.getMessage(), containsString("malformed signature for license [4056779d-b823-4c12-a9cb-efa4a8d8c422]"));
|
||||
assertThat(exception.getCause(), instanceOf(IllegalArgumentException.class));
|
||||
}
|
||||
|
||||
private License.Builder randomLicense(License.LicenseType type) {
|
||||
return License.builder()
|
||||
.uid(UUIDs.randomBase64UUID(random()))
|
||||
.type(type)
|
||||
.issueDate(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(randomIntBetween(1, 10)))
|
||||
.expiryDate(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(randomIntBetween(1, 1000)))
|
||||
.maxNodes(type == License.LicenseType.ENTERPRISE ? -1 : randomIntBetween(1, 100))
|
||||
.maxResourceUnits(type == License.LicenseType.ENTERPRISE ? randomIntBetween(1, 100) : -1)
|
||||
.issuedTo(randomAlphaOfLengthBetween(5, 50))
|
||||
.issuer(randomAlphaOfLengthBetween(5, 50));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
@ -33,4 +34,8 @@ public class LicenseUtilsTests extends ESTestCase {
|
|||
exception = new ElasticsearchSecurityException("msg");
|
||||
assertFalse(LicenseUtils.isLicenseExpiredException(exception));
|
||||
}
|
||||
|
||||
public void testVersionsUpToDate() {
|
||||
assertThat(LicenseUtils.compatibleLicenseVersion(DiscoveryNodes.EMPTY_NODES), equalTo(License.VERSION_CURRENT));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -366,6 +366,7 @@ public class ClusterStatsMonitoringDocTests extends BaseMonitoringDocTestCase<Cl
|
|||
+ "\"expiry_date\":\"2017-08-07T12:03:22.133Z\","
|
||||
+ "\"expiry_date_in_millis\":1502107402133,"
|
||||
+ "\"max_nodes\":2,"
|
||||
+ "\"max_resource_units\":null,"
|
||||
+ "\"issued_to\":\"customer\","
|
||||
+ "\"issuer\":\"elasticsearch\","
|
||||
+ "\"start_date_in_millis\":-1"
|
||||
|
|
|
@ -20,7 +20,7 @@ teardown:
|
|||
- do:
|
||||
license.get: {}
|
||||
|
||||
## a license object has 11 attributes
|
||||
## the rest API defaults to a v4 license output with 11 attributes
|
||||
- length: { license: 11 }
|
||||
|
||||
## bwc for licenses format
|
||||
|
|
|
@ -13,35 +13,39 @@ teardown:
|
|||
license.post:
|
||||
acknowledge: true
|
||||
body: |
|
||||
{"license":{"uid":"6e57906b-a8d1-4c1f-acb7-73a16edc3934","type":"enterprise","issue_date_in_millis":1523456691721,"expiry_date_in_millis":1838816691721,"max_nodes":50,"issued_to":"rest-test","issuer":"elasticsearch","signature":"AAAABAAAAA03e8BZRVXaCV4CpPGRAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAAZNhjABV6PRfa7P7sJgn70XCGoKtAVT75yU13JvKBd/UjD4TPhuZcztqZ/tcLEPxm/TSvGlogWmnw/Rw8xs8jMpBpKsJ+LOXjHhDdvXb2y7JJhCH8nlSEblMDRXysNvWpKe60Z/hb7hS4JynEUt0EBb6ji7BL42O07PNll1EGmkfsHazfs46iV91BG1VxXksI78XgWSaA0F/h7tvrNW9PTgsUaLo06InlQ8jA1dal90AoXp+MVDOHWQjVFZzUnO87/7lEb+VXt0IwchaW17ahihJqkCtGvKpWFwpuhx9xiFvkySN/g5LIVjYCvgBkiWExQ9p0Zzg3VoSlMBnVy0BWo=","start_date_in_millis":-1}}
|
||||
{"license":{"uid":"6e57906b-a8d1-4c1f-acb7-73a16edc3934","type":"enterprise","issue_date_in_millis":1523456691721,"expiry_date_in_millis":1838816691721,"max_nodes":null,"max_resource_units":50,"issued_to":"rest-test","issuer":"elasticsearch","signature":"AAAABQAAAA0sKPJdf9T6DItbXVJKAAAAIAo5/x6hrsGh1GqqrJmy4qgmEC7gK0U4zQ6q5ZEMhm4jAAABAKFCHrix7w/xPG14+wdhld1RmphDmXmHfL1xeuI33Ahr1mOUYZ30eR6GZuh7CnK8BQhfq+z63lgctJepWlvwDSgkOvXWLHrJun7YSCrzz1bism0ZHWw7Swb9DO7vePomVBo/Hm9+eX0pV4/cFQNMmbFaX11tqJZYBEO6sNASVAFL7A1ZcVoB2evweGU9pUQYvFvmyzzySf99miDo3NH0XYdownEdtoNgFfmqa3+koCP7onmRZ1h9jhsDOi30RX/DTDXQKW+XoREnOHCoOAJFxwip/c1qaQAOqp1H6+P20ZGr2sIPiU97OVEU9kulm+E+jgiVW3LwGheOXsUOd1B8Mp0=","start_date_in_millis":-1}}
|
||||
|
||||
- match: { license_status: "valid" }
|
||||
|
||||
- do:
|
||||
license.get: {}
|
||||
|
||||
## a license object has 11 attributes
|
||||
## a v4 (7.X compatible) license object has 11 attributes
|
||||
- length: { license: 11 }
|
||||
|
||||
## by default the enterprise license is "platinum"
|
||||
## by default the enterprise license is "platinum", and return "max_nodes"
|
||||
- match: { license.type: "platinum" }
|
||||
- match: { license.max_nodes: 50 }
|
||||
|
||||
- do:
|
||||
license.get:
|
||||
accept_enterprise: "true"
|
||||
|
||||
## a license object has 11 attributes
|
||||
- length: { license: 11 }
|
||||
## a v5 license object has 12 attributes
|
||||
- length: { license: 12 }
|
||||
|
||||
## opt-in to return real enterprise type
|
||||
- match: { license.type: "enterprise" }
|
||||
- match: { license.max_resource_units: 50 }
|
||||
- match: { license.max_nodes: null }
|
||||
|
||||
- do:
|
||||
license.get:
|
||||
accept_enterprise: "false"
|
||||
|
||||
## a license object has 11 attributes
|
||||
## a v4 license object has 11 attributes
|
||||
- length: { license: 11 }
|
||||
|
||||
## opt-out of real enterprise type
|
||||
- match: { license.type: "platinum" }
|
||||
- match: { license.max_nodes: 50 }
|
||||
|
|
Loading…
Reference in New Issue