Merge branch 'master' into security/redirect-to-login-on-401-xhr-response
Original commit: elastic/x-pack-elasticsearch@4a14381b93
This commit is contained in:
commit
a1e80e18c9
|
@ -1,3 +1,5 @@
|
|||
import org.elasticsearch.gradle.precommit.LicenseHeadersTask
|
||||
|
||||
File checkstyleSuppressions = file('checkstyle_suppressions.xml')
|
||||
subprojects {
|
||||
tasks.withType(Checkstyle) {
|
||||
|
@ -7,4 +9,9 @@ subprojects {
|
|||
suppressions: checkstyleSuppressions
|
||||
]
|
||||
}
|
||||
|
||||
tasks.withType(LicenseHeadersTask.class) {
|
||||
approvedLicenses = ['Elasticsearch Confidential']
|
||||
additionalLicense 'ESCON', 'Elasticsearch Confidential', 'ELASTICSEARCH CONFIDENTIAL'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,6 +101,7 @@ public class License implements ToXContent {
|
|||
case "gold":
|
||||
return GOLD;
|
||||
case "platinum":
|
||||
case "cloud_internal":
|
||||
case "internal": // bwc for 1.x subscription_type field
|
||||
return PLATINUM;
|
||||
default:
|
||||
|
@ -196,12 +197,42 @@ public class License implements ToXContent {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the operation mode of the license as computed from the license type
|
||||
* @return the operation mode of the license as computed from the license type or from
|
||||
* the license mode file
|
||||
*/
|
||||
public OperationMode operationMode() {
|
||||
synchronized (this) {
|
||||
if (canReadOperationModeFromFile() && operationModeFileWatcher != null) {
|
||||
return operationModeFileWatcher.getCurrentOperationMode();
|
||||
}
|
||||
}
|
||||
return operationMode;
|
||||
}
|
||||
|
||||
private boolean canReadOperationModeFromFile() {
|
||||
return type.equals("cloud_internal");
|
||||
}
|
||||
|
||||
private volatile OperationModeFileWatcher operationModeFileWatcher;
|
||||
|
||||
/**
|
||||
* Sets the operation mode file watcher for the license and initializes the
|
||||
* file watcher when the license type allows to override operation mode from file
|
||||
*/
|
||||
public synchronized void setOperationModeFileWatcher(final OperationModeFileWatcher operationModeFileWatcher) {
|
||||
this.operationModeFileWatcher = operationModeFileWatcher;
|
||||
if (canReadOperationModeFromFile()) {
|
||||
this.operationModeFileWatcher.init();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes operation mode file watcher, so unused license objects can be gc'ed
|
||||
*/
|
||||
public synchronized void removeOperationModeFileWatcher() {
|
||||
this.operationModeFileWatcher = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current license's status
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.core;
|
||||
|
||||
|
||||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.watcher.FileChangesListener;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* File based watcher for license {@link OperationMode}
|
||||
* Watches for changes in <code>licenseModePath</code>, use
|
||||
* {@link #getCurrentOperationMode()} to access the latest mode
|
||||
*
|
||||
* In case of failure to read a valid operation mode from <code>licenseModePath</code>,
|
||||
* the operation mode will default to PLATINUM
|
||||
*/
|
||||
public final class OperationModeFileWatcher extends FileChangesListener {
|
||||
private final ResourceWatcherService resourceWatcherService;
|
||||
private final Path licenseModePath;
|
||||
private final AtomicBoolean initialized = new AtomicBoolean();
|
||||
private final OperationMode defaultOperationMode = OperationMode.PLATINUM;
|
||||
private volatile OperationMode currentOperationMode = defaultOperationMode;
|
||||
private final ESLogger logger;
|
||||
private final Runnable onChange;
|
||||
|
||||
public OperationModeFileWatcher(ResourceWatcherService resourceWatcherService, Path licenseModePath,
|
||||
ESLogger logger, Runnable onChange) {
|
||||
this.resourceWatcherService = resourceWatcherService;
|
||||
this.licenseModePath = licenseModePath;
|
||||
this.logger = logger;
|
||||
this.onChange = onChange;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
final FileWatcher watcher = new FileWatcher(licenseModePath);
|
||||
watcher.addListener(this);
|
||||
try {
|
||||
resourceWatcherService.add(watcher, ResourceWatcherService.Frequency.HIGH);
|
||||
if (Files.exists(licenseModePath)) {
|
||||
onChange(licenseModePath);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("couldn't initialize watching license mode file", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current operation mode based on license mode file.
|
||||
* Defaults to {@link OperationMode#PLATINUM}
|
||||
*/
|
||||
public OperationMode getCurrentOperationMode() {
|
||||
return currentOperationMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileInit(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileCreated(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileDeleted(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFileChanged(Path file) {
|
||||
onChange(file);
|
||||
}
|
||||
|
||||
private synchronized void onChange(Path file) {
|
||||
if (file.equals(licenseModePath)) {
|
||||
currentOperationMode = defaultOperationMode;
|
||||
if (Files.exists(licenseModePath)
|
||||
&& Files.isReadable(licenseModePath)) {
|
||||
final byte[] content;
|
||||
try {
|
||||
content = Files.readAllBytes(licenseModePath);
|
||||
} catch (IOException e) {
|
||||
logger.error("couldn't read operation mode from [{}]", e, licenseModePath.toAbsolutePath().toString());
|
||||
return;
|
||||
}
|
||||
String operationMode = new String(content, StandardCharsets.UTF_8);
|
||||
try {
|
||||
currentOperationMode = OperationMode.resolve(operationMode);
|
||||
} catch (IllegalArgumentException e) {
|
||||
logger.error("invalid operation mode in [{}]", e, licenseModePath.toAbsolutePath().toString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
onChange.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.watcher.FileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import static org.elasticsearch.license.core.OperationModeFileWatcherTests.writeMode;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
|
||||
public class LicenseOperationModeUpdateTests extends ESTestCase {
|
||||
|
||||
private OperationModeFileWatcher operationModeFileWatcher;
|
||||
private Path licenseModeFile;
|
||||
private ResourceWatcherService resourceWatcherService;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
licenseModeFile = createTempFile();
|
||||
resourceWatcherService = mock(ResourceWatcherService.class);
|
||||
operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService, licenseModeFile, logger, () -> {});
|
||||
}
|
||||
|
||||
public void testLicenseOperationModeUpdate() throws Exception {
|
||||
String type = randomFrom("trial", "basic", "standard", "gold", "platinum");
|
||||
License license = License.builder()
|
||||
.uid("id")
|
||||
.expiryDate(0)
|
||||
.issueDate(0)
|
||||
.issuedTo("elasticsearch")
|
||||
.issuer("issuer")
|
||||
.type(type)
|
||||
.maxNodes(1)
|
||||
.build();
|
||||
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.resolve(type)));
|
||||
writeMode("gold", licenseModeFile);
|
||||
license.setOperationModeFileWatcher(operationModeFileWatcher);
|
||||
verifyZeroInteractions(resourceWatcherService);
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.resolve(type)));
|
||||
}
|
||||
|
||||
public void testCloudInternalLicenseOperationModeUpdate() throws Exception {
|
||||
License license = License.builder()
|
||||
.uid("id")
|
||||
.expiryDate(0)
|
||||
.issueDate(0)
|
||||
.issuedTo("elasticsearch")
|
||||
.issuer("issuer")
|
||||
.type("cloud_internal")
|
||||
.maxNodes(1)
|
||||
.build();
|
||||
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
writeMode("gold", licenseModeFile);
|
||||
license.setOperationModeFileWatcher(operationModeFileWatcher);
|
||||
verify(resourceWatcherService, times(1)).add(any(FileWatcher.class), eq(ResourceWatcherService.Frequency.HIGH));
|
||||
assertThat(license.operationMode(), equalTo(License.OperationMode.GOLD));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class OperationModeFileWatcherTests extends ESTestCase {
|
||||
private ResourceWatcherService watcherService;
|
||||
private TestThreadPool threadPool;
|
||||
private Path licenseModePath;
|
||||
private OperationModeFileWatcher operationModeFileWatcher;
|
||||
private AtomicInteger onChangeCounter;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
threadPool = new TestThreadPool("license mode file watcher tests");
|
||||
Settings settings = Settings.builder()
|
||||
.put("resource.reload.interval.high", "10ms")
|
||||
.build();
|
||||
watcherService = new ResourceWatcherService(settings,
|
||||
threadPool);
|
||||
watcherService.start();
|
||||
licenseModePath = createTempFile();
|
||||
onChangeCounter = new AtomicInteger();
|
||||
operationModeFileWatcher = new OperationModeFileWatcher(watcherService, licenseModePath, logger,
|
||||
() -> onChangeCounter.incrementAndGet());
|
||||
}
|
||||
|
||||
@After
|
||||
public void shutdown() throws InterruptedException {
|
||||
terminate(threadPool);
|
||||
watcherService.stop();
|
||||
}
|
||||
|
||||
public void testInit() throws Exception {
|
||||
writeMode("gold");
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(onChangeCounter.get(), equalTo(2));
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD));
|
||||
}
|
||||
|
||||
public void testUpdateModeFromFile() throws Exception {
|
||||
Files.delete(licenseModePath);
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
writeMode("gold");
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD)));
|
||||
writeMode("basic");
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.BASIC)));
|
||||
assertThat(onChangeCounter.get(), equalTo(2));
|
||||
}
|
||||
|
||||
public void testDeleteModeFromFile() throws Exception {
|
||||
Files.delete(licenseModePath);
|
||||
operationModeFileWatcher.init();
|
||||
writeMode("gold");
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD)));
|
||||
Files.delete(licenseModePath);
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM)));
|
||||
assertThat(onChangeCounter.get(), equalTo(2));
|
||||
}
|
||||
|
||||
public void testInvalidModeFromFile() throws Exception {
|
||||
writeMode("invalid");
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
operationModeFileWatcher.onFileChanged(licenseModePath);
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
}
|
||||
|
||||
public void testLicenseModeFileIsDirectory() throws Exception {
|
||||
licenseModePath = createTempDir();
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
operationModeFileWatcher.onFileChanged(licenseModePath);
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
}
|
||||
|
||||
public void testLicenseModeFileCreatedAfterInit() throws Exception {
|
||||
Files.delete(licenseModePath);
|
||||
operationModeFileWatcher.init();
|
||||
assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.PLATINUM));
|
||||
Path tempFile = createTempFile();
|
||||
writeMode("gold", tempFile);
|
||||
licenseModePath = tempFile;
|
||||
assertBusy(() -> assertThat(operationModeFileWatcher.getCurrentOperationMode(), equalTo(License.OperationMode.GOLD)));
|
||||
}
|
||||
|
||||
private void writeMode(String mode) throws IOException {
|
||||
writeMode(mode, licenseModePath);
|
||||
}
|
||||
|
||||
static void writeMode(String mode, Path file) throws IOException {
|
||||
Files.write(file, mode.getBytes(StandardCharsets.UTF_8), StandardOpenOption.CREATE);
|
||||
}
|
||||
}
|
|
@ -3,7 +3,5 @@ subprojects {
|
|||
project.forbiddenPatterns {
|
||||
exclude '**/*.key'
|
||||
}
|
||||
// someone figure out what the x-plugins logic should be
|
||||
project.licenseHeaders.enabled = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ project.sourceSets.test.output.dir(outputDir, builtBy: copyXPackPluginProps)
|
|||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.audit.enabled', 'true'
|
||||
setting 'xpack.security.audit.outputs', 'index'
|
||||
setting 'logger.level', 'DEBUG'
|
||||
|
|
|
@ -38,11 +38,10 @@ public class IndexAuditIT extends ESIntegTestCase {
|
|||
|
||||
@AwaitsFix(bugUrl = "https://github.com/elastic/x-plugins/issues/2354")
|
||||
public void testShieldIndexAuditTrailWorking() throws Exception {
|
||||
try (Response response = getRestClient().performRequest("GET", "/",
|
||||
Response response = getRestClient().performRequest("GET", "/",
|
||||
new BasicHeader(UsernamePasswordToken.BASIC_AUTH_HEADER,
|
||||
UsernamePasswordToken.basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()))))) {
|
||||
UsernamePasswordToken.basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()))));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
}
|
||||
final AtomicReference<ClusterState> lastClusterState = new AtomicReference<>();
|
||||
final AtomicBoolean indexExists = new AtomicBoolean(false);
|
||||
boolean found = awaitBusy(() -> {
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
subprojects {
|
||||
tasks.withType(org.elasticsearch.gradle.precommit.LicenseHeadersTask) {
|
||||
// someone figure out what the x-plugins logic should be
|
||||
project.licenseHeaders.enabled = false
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ integTest {
|
|||
'search/80_date_math_index_names/Missing index with catch'].join(',')
|
||||
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.watcher.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setupCommand 'setupDummyUser',
|
||||
|
|
|
@ -7,29 +7,30 @@ package org.elasticsearch.xpack.security;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class RestIT extends ESRestTestCase {
|
||||
public class CoreWithSecurityClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String USER = "test_user";
|
||||
private static final String PASS = "changeme";
|
||||
|
||||
public RestIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public CoreWithSecurityClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -14,7 +14,7 @@ import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
|||
import org.elasticsearch.xpack.watcher.execution.ManualExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.execution.ManualExecutionTests.ExecutionRunner;
|
||||
import org.elasticsearch.xpack.watcher.history.WatchRecord;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.delete.DeleteWatchResponse;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.get.GetWatchRequest;
|
||||
|
@ -65,7 +65,7 @@ public class GroovyManualExecutionIT extends AbstractWatcherIntegrationTestCase
|
|||
WatchSourceBuilder watchBuilder = watchBuilder()
|
||||
.trigger(schedule(cron("0 0 0 1 * ? 2099")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.condition(new ScriptCondition((new Script.Builder.Inline("sleep 100; return true")).build()))
|
||||
.condition(new ScriptCondition((new WatcherScript.Builder.Inline("sleep 100; return true")).build()))
|
||||
.addAction("log", loggingAction("foobar"));
|
||||
|
||||
Watch watch = watchParser().parse("_id", false, watchBuilder.buildAsBytes(XContentType.JSON));
|
||||
|
@ -80,7 +80,7 @@ public class GroovyManualExecutionIT extends AbstractWatcherIntegrationTestCase
|
|||
WatchSourceBuilder watchBuilder = watchBuilder()
|
||||
.trigger(schedule(cron("0 0 0 1 * ? 2099")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.condition(new ScriptCondition((new Script.Builder.Inline("sleep 10000; return true")).build()))
|
||||
.condition(new ScriptCondition((new WatcherScript.Builder.Inline("sleep 10000; return true")).build()))
|
||||
.defaultThrottlePeriod(new TimeValue(1, TimeUnit.HOURS))
|
||||
.addAction("log", loggingAction("foobar"));
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.elasticsearch.messy.tests;
|
|||
import org.elasticsearch.action.search.SearchRequestBuilder;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.Histogram;
|
||||
|
@ -16,8 +17,7 @@ import org.elasticsearch.threadpool.ThreadPool;
|
|||
import org.elasticsearch.xpack.watcher.condition.script.ExecutableScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
import org.junit.AfterClass;
|
||||
|
@ -28,7 +28,7 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.getScriptServiceProxy;
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.createScriptService;
|
||||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContext;
|
||||
|
||||
public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase {
|
||||
|
@ -46,7 +46,7 @@ public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase
|
|||
}
|
||||
|
||||
private static ThreadPool THREAD_POOL;
|
||||
private ScriptServiceProxy scriptService;
|
||||
private ScriptService scriptService;
|
||||
|
||||
@BeforeClass
|
||||
public static void startThreadPool() {
|
||||
|
@ -55,7 +55,7 @@ public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase
|
|||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
scriptService = getScriptServiceProxy(THREAD_POOL);
|
||||
scriptService = createScriptService(THREAD_POOL);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
|
@ -83,7 +83,7 @@ public class GroovyScriptConditionIT extends AbstractWatcherIntegrationTestCase
|
|||
SearchResponse unmetResponse = builder.get();
|
||||
|
||||
ExecutableScriptCondition condition =
|
||||
new ExecutableScriptCondition(new ScriptCondition(Script.inline(
|
||||
new ExecutableScriptCondition(new ScriptCondition(WatcherScript.inline(
|
||||
String.join(
|
||||
" ",
|
||||
"if (ctx.payload.hits.total < 1) return false;",
|
||||
|
|
|
@ -1,215 +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.messy.tests;
|
||||
|
||||
import org.elasticsearch.action.search.SearchRequest;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.action.search.SearchType;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.elasticsearch.xpack.watcher.history.HistoryStore;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherDateTimeUtils;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.execute.ExecuteWatchResponse;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse;
|
||||
import org.elasticsearch.xpack.watcher.trigger.schedule.ScheduleTriggerEvent;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.index.query.QueryBuilders.matchQuery;
|
||||
import static org.elasticsearch.search.aggregations.AggregationBuilders.dateHistogram;
|
||||
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
|
||||
import static org.elasticsearch.xpack.watcher.actions.ActionBuilders.indexAction;
|
||||
import static org.elasticsearch.xpack.watcher.client.WatchSourceBuilders.watchBuilder;
|
||||
import static org.elasticsearch.xpack.watcher.input.InputBuilders.searchInput;
|
||||
import static org.elasticsearch.xpack.watcher.input.InputBuilders.simpleInput;
|
||||
import static org.elasticsearch.xpack.watcher.transform.TransformBuilders.scriptTransform;
|
||||
import static org.elasticsearch.xpack.watcher.trigger.TriggerBuilders.schedule;
|
||||
import static org.elasticsearch.xpack.watcher.trigger.schedule.Schedules.cron;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.hasKey;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class IndexActionIT extends AbstractWatcherIntegrationTestCase {
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Plugin>> pluginTypes() {
|
||||
List<Class<? extends Plugin>> types = super.pluginTypes();
|
||||
types.add(GroovyPlugin.class);
|
||||
return types;
|
||||
}
|
||||
|
||||
public void testSimple() throws Exception {
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder()
|
||||
.trigger(schedule(cron("0/1 * * * * ? 2020")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.addAction("index-buckets", indexAction("idx", "type").setExecutionTimeField("@timestamp")))
|
||||
.get();
|
||||
|
||||
assertThat(putWatchResponse.isCreated(), is(true));
|
||||
|
||||
DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC);
|
||||
|
||||
ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id")
|
||||
.setTriggerEvent(new ScheduleTriggerEvent(now, now))
|
||||
.get();
|
||||
|
||||
assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed"));
|
||||
|
||||
flush("idx");
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("idx").setTypes("type").get();
|
||||
assertThat(searchResponse.getHits().totalHits(), is(1L));
|
||||
SearchHit hit = searchResponse.getHits().getAt(0);
|
||||
if (timeWarped()) {
|
||||
assertThat(hit.getSource(), hasEntry("@timestamp", (Object) WatcherDateTimeUtils.formatDate(now)));
|
||||
} else {
|
||||
assertThat(hit.getSource(), hasKey("@timestamp"));
|
||||
DateTime timestamp = WatcherDateTimeUtils.parseDate((String) hit.getSource().get("@timestamp"));
|
||||
assertThat(timestamp.isEqual(now) || timestamp.isAfter(now), is(true));
|
||||
}
|
||||
assertThat(hit.getSource(), hasEntry("foo", (Object) "bar"));
|
||||
}
|
||||
|
||||
public void testSimpleWithDocField() throws Exception {
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder()
|
||||
.trigger(schedule(cron("0/1 * * * * ? 2020")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.addAction("index-buckets",
|
||||
scriptTransform("return [ '_doc' : ctx.payload ]"),
|
||||
indexAction("idx", "type").setExecutionTimeField("@timestamp")))
|
||||
|
||||
.get();
|
||||
|
||||
assertThat(putWatchResponse.isCreated(), is(true));
|
||||
|
||||
DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC);
|
||||
|
||||
ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id")
|
||||
.setTriggerEvent(new ScheduleTriggerEvent(now, now))
|
||||
.get();
|
||||
|
||||
assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed"));
|
||||
|
||||
flush("idx");
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("idx").setTypes("type").get();
|
||||
assertThat(searchResponse.getHits().totalHits(), is(1L));
|
||||
SearchHit hit = searchResponse.getHits().getAt(0);
|
||||
if (timeWarped()) {
|
||||
assertThat(hit.getSource(), hasEntry("@timestamp", (Object) WatcherDateTimeUtils.formatDate(now)));
|
||||
} else {
|
||||
assertThat(hit.getSource(), hasKey("@timestamp"));
|
||||
DateTime timestamp = WatcherDateTimeUtils.parseDate((String) hit.getSource().get("@timestamp"));
|
||||
assertThat(timestamp.isEqual(now) || timestamp.isAfter(now), is(true));
|
||||
}
|
||||
assertThat(hit.getSource(), hasEntry("foo", (Object) "bar"));
|
||||
}
|
||||
|
||||
public void testSimpleWithDocFieldWrongFieldType() throws Exception {
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder()
|
||||
.trigger(schedule(cron("0/1 * * * * ? 2020")))
|
||||
.input(simpleInput("foo", "bar"))
|
||||
.addAction("index-buckets",
|
||||
scriptTransform("return [ '_doc' : 1 ]"),
|
||||
indexAction("idx", "type").setExecutionTimeField("@timestamp")))
|
||||
.get();
|
||||
|
||||
assertThat(putWatchResponse.isCreated(), is(true));
|
||||
|
||||
DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC);
|
||||
|
||||
ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id")
|
||||
.setTriggerEvent(new ScheduleTriggerEvent(now, now))
|
||||
.setRecordExecution(true)
|
||||
.get();
|
||||
|
||||
assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed"));
|
||||
|
||||
flush();
|
||||
refresh();
|
||||
|
||||
assertThat(client().admin().indices().prepareExists("idx").get().isExists(), is(false));
|
||||
|
||||
assertThat(docCount(HistoryStore.INDEX_PREFIX + "*", HistoryStore.DOC_TYPE, searchSource()
|
||||
.query(matchQuery("result.actions.status", "failure"))), is(1L));
|
||||
|
||||
}
|
||||
|
||||
public void testIndexAggsBucketsAsDocuments() throws Exception {
|
||||
DateTime now = timeWarped() ? timeWarp().clock().now(DateTimeZone.UTC) : DateTime.now(DateTimeZone.UTC);
|
||||
long bucketCount = randomIntBetween(2, 5);
|
||||
for (int i = 0; i < bucketCount; i++) {
|
||||
index("idx", "type", jsonBuilder().startObject()
|
||||
.field("timestamp", now.minusDays(i))
|
||||
.endObject());
|
||||
}
|
||||
|
||||
flush("idx");
|
||||
refresh();
|
||||
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id").setSource(watchBuilder()
|
||||
.trigger(schedule(cron("0/1 * * * * ? 2020")))
|
||||
.input(searchInput(new SearchRequest("idx")
|
||||
.types("type")
|
||||
.searchType(SearchType.QUERY_THEN_FETCH)
|
||||
.source(searchSource()
|
||||
.aggregation(dateHistogram("trend")
|
||||
.field("timestamp")
|
||||
.dateHistogramInterval(DateHistogramInterval.DAY)))))
|
||||
.addAction("index-buckets",
|
||||
|
||||
// this transform takes the bucket list and assigns it to `_doc`
|
||||
// this means each bucket will be indexed as a separate doc,
|
||||
// so we expect to have the same number of documents as the number
|
||||
// of buckets.
|
||||
scriptTransform("return [ '_doc' : ctx.payload.aggregations.trend.buckets]"),
|
||||
|
||||
indexAction("idx", "bucket").setExecutionTimeField("@timestamp")))
|
||||
|
||||
.get();
|
||||
|
||||
assertThat(putWatchResponse.isCreated(), is(true));
|
||||
|
||||
ExecuteWatchResponse executeWatchResponse = watcherClient().prepareExecuteWatch("_id")
|
||||
.setTriggerEvent(new ScheduleTriggerEvent(now, now))
|
||||
.get();
|
||||
|
||||
assertThat(executeWatchResponse.getRecordSource().getValue("state"), is((Object) "executed"));
|
||||
|
||||
flush("idx");
|
||||
refresh();
|
||||
|
||||
SearchResponse searchResponse = client().prepareSearch("idx").setTypes("bucket")
|
||||
.addSort("key", SortOrder.DESC)
|
||||
.get();
|
||||
assertThat(searchResponse.getHits().getTotalHits(), is(bucketCount));
|
||||
DateTime key = now.withMillisOfDay(0);
|
||||
int i = 0;
|
||||
for (SearchHit hit : searchResponse.getHits()) {
|
||||
if (timeWarped()) {
|
||||
assertThat(hit.getSource(), hasEntry("@timestamp", (Object) WatcherDateTimeUtils.formatDate(now)));
|
||||
} else {
|
||||
assertThat(hit.getSource(), hasKey("@timestamp"));
|
||||
DateTime timestamp = WatcherDateTimeUtils.parseDate((String) hit.getSource().get("@timestamp"));
|
||||
assertThat(timestamp.isEqual(now) || timestamp.isAfter(now), is(true));
|
||||
}
|
||||
assertThat(hit.getSource(), hasEntry("key", (Object) key.getMillis()));
|
||||
key = key.minusDays(1);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,9 +6,6 @@
|
|||
package org.elasticsearch.messy.tests;
|
||||
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.SuppressForbidden;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
|
@ -19,9 +16,8 @@ import org.elasticsearch.script.ScriptSettings;
|
|||
import org.elasticsearch.script.groovy.GroovyScriptEngineService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.junit.Ignore;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -29,7 +25,7 @@ import java.util.Collections;
|
|||
@Ignore // not a test.
|
||||
@SuppressForbidden(reason = "gradle is broken and tries to run me as a test")
|
||||
public final class MessyTestUtils {
|
||||
public static ScriptServiceProxy getScriptServiceProxy(ThreadPool tp) throws Exception {
|
||||
public static ScriptService createScriptService(ThreadPool tp) throws Exception {
|
||||
Settings settings = Settings.builder()
|
||||
.put("script.inline", "true")
|
||||
.put("script.indexed", "true")
|
||||
|
@ -37,10 +33,10 @@ public final class MessyTestUtils {
|
|||
.build();
|
||||
GroovyScriptEngineService groovyScriptEngineService = new GroovyScriptEngineService(settings);
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(Collections.singleton(groovyScriptEngineService));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Arrays.asList(ScriptServiceProxy.INSTANCE));
|
||||
ScriptContextRegistry scriptContextRegistry = new ScriptContextRegistry(Arrays.asList(WatcherScript.CTX_PLUGIN));
|
||||
|
||||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, scriptContextRegistry);
|
||||
return ScriptServiceProxy.of(new ScriptService(settings, new Environment(settings),
|
||||
new ResourceWatcherService(settings, tp), scriptEngineRegistry, scriptContextRegistry, scriptSettings));
|
||||
return new ScriptService(settings, new Environment(settings), new ResourceWatcherService(settings, tp),
|
||||
scriptEngineRegistry, scriptContextRegistry, scriptSettings);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.action.search.ShardSearchFailure;
|
|||
import org.elasticsearch.common.text.Text;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.search.SearchShardTarget;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
|
@ -20,11 +21,10 @@ import org.elasticsearch.search.internal.InternalSearchHits;
|
|||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ExecutableScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
import org.junit.After;
|
||||
|
@ -40,7 +40,7 @@ import static org.mockito.Mockito.when;
|
|||
*/
|
||||
public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase {
|
||||
private ThreadPool tp = null;
|
||||
private ScriptServiceProxy scriptService;
|
||||
private ScriptService scriptService;
|
||||
|
||||
@Override
|
||||
protected List<Class<? extends Plugin>> pluginTypes() {
|
||||
|
@ -52,7 +52,7 @@ public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase
|
|||
@Before
|
||||
public void init() throws Exception {
|
||||
tp = new TestThreadPool(ThreadPool.Names.SAME);
|
||||
scriptService = MessyTestUtils.getScriptServiceProxy(tp);
|
||||
scriptService = MessyTestUtils.createScriptService(tp);
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -73,7 +73,7 @@ public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase
|
|||
.get();
|
||||
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5").build()),
|
||||
new ScriptCondition(WatcherScript.inline("ctx.payload.aggregations.rate.buckets[0]?.doc_count >= 5").build()),
|
||||
logger, scriptService);
|
||||
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
|
@ -92,7 +92,7 @@ public class ScriptConditionSearchIT extends AbstractWatcherIntegrationTestCase
|
|||
|
||||
public void testExecuteAccessHits() throws Exception {
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(new ScriptCondition(
|
||||
Script.inline("ctx.payload.hits?.hits[0]?._score == 1.0").build()), logger, scriptService);
|
||||
WatcherScript.inline("ctx.payload.hits?.hits[0]?._score == 1.0").build()), logger, scriptService);
|
||||
InternalSearchHit hit = new InternalSearchHit(0, "1", new Text("type"), null);
|
||||
hit.score(1f);
|
||||
hit.shard(new SearchShardTarget("a", new Index("a", "testUUID"), 0));
|
||||
|
|
|
@ -15,17 +15,17 @@ import org.elasticsearch.common.xcontent.XContentFactory;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.script.GeneralScriptException;
|
||||
import org.elasticsearch.script.ScriptException;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptService.ScriptType;
|
||||
import org.elasticsearch.search.internal.InternalSearchResponse;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ExecutableScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptCondition;
|
||||
import org.elasticsearch.xpack.watcher.condition.script.ScriptConditionFactory;
|
||||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.watch.Payload;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.DateTimeZone;
|
||||
|
@ -36,7 +36,7 @@ import java.io.IOException;
|
|||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.getScriptServiceProxy;
|
||||
import static org.elasticsearch.messy.tests.MessyTestUtils.createScriptService;
|
||||
import static org.elasticsearch.xpack.watcher.support.Exceptions.illegalArgument;
|
||||
import static org.elasticsearch.xpack.watcher.test.WatcherTestUtils.mockExecutionContext;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -57,18 +57,18 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testExecute() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("ctx.payload.hits.total > 1").build()), logger, scriptService);
|
||||
new ScriptCondition(WatcherScript.inline("ctx.payload.hits.total > 1").build()), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
assertFalse(condition.execute(ctx).met());
|
||||
}
|
||||
|
||||
public void testExecuteMergedParams() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
Script script = Script.inline("ctx.payload.hits.total > threshold")
|
||||
.lang(Script.DEFAULT_LANG).params(singletonMap("threshold", 1)).build();
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
WatcherScript script = WatcherScript.inline("ctx.payload.hits.total > threshold")
|
||||
.lang(WatcherScript.DEFAULT_LANG).params(singletonMap("threshold", 1)).build();
|
||||
ExecutableScriptCondition executable = new ExecutableScriptCondition(new ScriptCondition(script), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
|
@ -76,7 +76,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testParserValid() throws Exception {
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
|
||||
XContentBuilder builder = createConditionContent("ctx.payload.hits.total > 1", null, ScriptType.INLINE);
|
||||
|
||||
|
@ -103,7 +103,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testParserInvalid() throws Exception {
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory factory = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject().endObject();
|
||||
XContentParser parser = XContentFactory.xContent(builder.bytes()).createParser(builder.bytes());
|
||||
|
@ -118,7 +118,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testScriptConditionParserBadScript() throws Exception {
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
ScriptType scriptType = randomFrom(ScriptType.values());
|
||||
String script;
|
||||
switch (scriptType) {
|
||||
|
@ -139,7 +139,7 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testScriptConditionParser_badLang() throws Exception {
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), getScriptServiceProxy(tp));
|
||||
ScriptConditionFactory conditionParser = new ScriptConditionFactory(Settings.builder().build(), createScriptService(tp));
|
||||
ScriptType scriptType = ScriptType.INLINE;
|
||||
String script = "return true";
|
||||
XContentBuilder builder = createConditionContent(script, "not_a_valid_lang", scriptType);
|
||||
|
@ -152,9 +152,9 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testScriptConditionThrowException() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("null.foo").build()), logger, scriptService);
|
||||
new ScriptCondition(WatcherScript.inline("null.foo").build()), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
ScriptException exception = expectThrows(ScriptException.class, () -> condition.execute(ctx));
|
||||
|
@ -162,9 +162,9 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testScriptConditionReturnObjectThrowsException() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("return new Object()").build()), logger, scriptService);
|
||||
new ScriptCondition(WatcherScript.inline("return new Object()").build()), logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new Payload.XContent(response));
|
||||
Exception exception = expectThrows(GeneralScriptException.class, () -> condition.execute(ctx));
|
||||
|
@ -173,9 +173,9 @@ public class ScriptConditionTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testScriptConditionAccessCtx() throws Exception {
|
||||
ScriptServiceProxy scriptService = getScriptServiceProxy(tp);
|
||||
ScriptService scriptService = createScriptService(tp);
|
||||
ExecutableScriptCondition condition = new ExecutableScriptCondition(
|
||||
new ScriptCondition(Script.inline("ctx.trigger.scheduled_time.getMillis() < new Date().time ").build()),
|
||||
new ScriptCondition(WatcherScript.inline("ctx.trigger.scheduled_time.getMillis() < new Date().time ").build()),
|
||||
logger, scriptService);
|
||||
SearchResponse response = new SearchResponse(InternalSearchResponse.empty(), "", 3, 3, 500L, new ShardSearchFailure[0]);
|
||||
WatchExecutionContext ctx = mockExecutionContext("_name", new DateTime(DateTimeZone.UTC), new Payload.XContent(response));
|
||||
|
|
|
@ -13,7 +13,7 @@ import org.elasticsearch.common.io.Streams;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.groovy.GroovyPlugin;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.test.AbstractWatcherIntegrationTestCase;
|
||||
import org.elasticsearch.xpack.watcher.test.WatcherTestUtils;
|
||||
import org.elasticsearch.xpack.watcher.transport.actions.put.PutWatchResponse;
|
||||
|
@ -72,10 +72,10 @@ public class TransformIT extends AbstractWatcherIntegrationTestCase {
|
|||
}
|
||||
|
||||
public void testScriptTransform() throws Exception {
|
||||
final Script script;
|
||||
final WatcherScript script;
|
||||
if (randomBoolean()) {
|
||||
logger.info("testing script transform with an inline script");
|
||||
script = Script.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
script = WatcherScript.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
} else if (randomBoolean()) {
|
||||
logger.info("testing script transform with an indexed script");
|
||||
client().admin().cluster().preparePutStoredScript()
|
||||
|
@ -83,10 +83,10 @@ public class TransformIT extends AbstractWatcherIntegrationTestCase {
|
|||
.setScriptLang("groovy")
|
||||
.setSource(new BytesArray("{\"script\" : \"return [key3 : ctx.payload.key1 + ctx.payload.key2]\"}"))
|
||||
.get();
|
||||
script = Script.indexed("_id").lang("groovy").build();
|
||||
script = WatcherScript.indexed("_id").lang("groovy").build();
|
||||
} else {
|
||||
logger.info("testing script transform with a file script");
|
||||
script = Script.file("my-script").lang("groovy").build();
|
||||
script = WatcherScript.file("my-script").lang("groovy").build();
|
||||
}
|
||||
|
||||
// put a watch that has watch level transform:
|
||||
|
@ -182,8 +182,8 @@ public class TransformIT extends AbstractWatcherIntegrationTestCase {
|
|||
}
|
||||
|
||||
public void testChainTransform() throws Exception {
|
||||
final Script script1 = Script.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
final Script script2 = Script.inline("return [key4 : ctx.payload.key3 + 10]").lang("groovy").build();
|
||||
final WatcherScript script1 = WatcherScript.inline("return [key3 : ctx.payload.key1 + ctx.payload.key2]").lang("groovy").build();
|
||||
final WatcherScript script2 = WatcherScript.inline("return [key4 : ctx.payload.key3 + 10]").lang("groovy").build();
|
||||
// put a watch that has watch level transform:
|
||||
PutWatchResponse putWatchResponse = watcherClient().preparePutWatch("_id1")
|
||||
.setSource(watchBuilder()
|
||||
|
|
|
@ -28,7 +28,6 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
|||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.actions.ActionWrapper;
|
||||
import org.elasticsearch.xpack.watcher.actions.ExecutableActions;
|
||||
|
@ -41,7 +40,7 @@ import org.elasticsearch.xpack.watcher.input.search.SearchInput;
|
|||
import org.elasticsearch.xpack.watcher.input.search.SearchInputFactory;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
|
@ -190,7 +189,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
|||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.inline(TEMPLATE_QUERY).lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.inline(TEMPLATE_QUERY).lang("mustache").params(params).build();
|
||||
|
||||
SearchRequest request = client().prepareSearch()
|
||||
.setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
|
||||
|
@ -224,7 +223,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
|||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.indexed("test-template").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.indexed("test-template").lang("mustache").params(params).build();
|
||||
|
||||
jsonBuilder().value(TextTemplate.indexed("test-template").params(params).build()).bytes();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
|
||||
|
@ -252,7 +251,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
|||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.file("test_disk_template").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.file("test_disk_template").lang("mustache").params(params).build();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchInput.DEFAULT_SEARCH_TYPE)
|
||||
.setIndices("test-search-index").request();
|
||||
|
||||
|
@ -347,7 +346,8 @@ public class SearchInputIT extends ESIntegTestCase {
|
|||
timeValueSeconds(5));
|
||||
}
|
||||
|
||||
private SearchInput.Result executeSearchInput(SearchRequest request, Script template, WatchExecutionContext ctx) throws IOException {
|
||||
private SearchInput.Result executeSearchInput(SearchRequest request, WatcherScript template,
|
||||
WatchExecutionContext ctx) throws IOException {
|
||||
createIndex("test-search-index");
|
||||
ensureGreen("test-search-index");
|
||||
SearchInput.Builder siBuilder = SearchInput.builder(new WatcherSearchTemplateRequest(request, template));
|
||||
|
@ -362,15 +362,15 @@ public class SearchInputIT extends ESIntegTestCase {
|
|||
protected WatcherSearchTemplateService watcherSearchTemplateService() {
|
||||
String master = internalCluster().getMasterName();
|
||||
return new WatcherSearchTemplateService(internalCluster().clusterService(master).getSettings(),
|
||||
ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class, master)),
|
||||
internalCluster().getInstance(ScriptService.class, master),
|
||||
internalCluster().getInstance(IndicesQueriesRegistry.class, master),
|
||||
internalCluster().getInstance(AggregatorParsers.class, master),
|
||||
internalCluster().getInstance(Suggesters.class, master)
|
||||
);
|
||||
}
|
||||
|
||||
protected ScriptServiceProxy scriptService() {
|
||||
return ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class));
|
||||
protected ScriptService scriptService() {
|
||||
return internalCluster().getInstance(ScriptService.class);
|
||||
}
|
||||
|
||||
private XContentSource toXContentSource(SearchInput.Result result) throws IOException {
|
||||
|
@ -387,7 +387,7 @@ public class SearchInputIT extends ESIntegTestCase {
|
|||
|
||||
@Override
|
||||
public ScriptContext.Plugin getCustomScriptContexts() {
|
||||
return ScriptServiceProxy.INSTANCE;
|
||||
return WatcherScript.CTX_PLUGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
|
|||
import org.elasticsearch.search.suggest.Suggesters;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.test.ESIntegTestCase.ClusterScope;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.watcher.actions.ExecutableActions;
|
||||
import org.elasticsearch.xpack.watcher.condition.always.ExecutableAlwaysCondition;
|
||||
|
@ -40,7 +39,7 @@ import org.elasticsearch.xpack.watcher.execution.TriggeredExecutionContext;
|
|||
import org.elasticsearch.xpack.watcher.execution.WatchExecutionContext;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.ExecutableSimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.input.simple.SimpleInput;
|
||||
import org.elasticsearch.xpack.watcher.support.Script;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.elasticsearch.xpack.watcher.support.init.proxy.WatcherClientProxy;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateRequest;
|
||||
import org.elasticsearch.xpack.watcher.support.search.WatcherSearchTemplateService;
|
||||
|
@ -348,7 +347,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
}
|
||||
if (templateName != null) {
|
||||
assertThat(executable.transform().getRequest().getTemplate(),
|
||||
equalTo(Script.file("template1").build()));
|
||||
equalTo(WatcherScript.file("template1").build()));
|
||||
}
|
||||
SearchSourceBuilder source = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
|
||||
assertThat(executable.transform().getRequest().getRequest().source(), equalTo(source));
|
||||
|
@ -381,7 +380,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.inline(templateQuery).lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.inline(templateQuery).lang("mustache").params(params).build();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchTransform.DEFAULT_SEARCH_TYPE)
|
||||
.setIndices("test-search-index").request();
|
||||
|
||||
|
@ -415,7 +414,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.indexed("test-script").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.indexed("test-script").lang("mustache").params(params).build();
|
||||
|
||||
SearchRequest request = client()
|
||||
.prepareSearch()
|
||||
|
@ -441,7 +440,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("seconds_param", "30s");
|
||||
|
||||
Script template = Script.file("test_disk_template").lang("mustache").params(params).build();
|
||||
WatcherScript template = WatcherScript.file("test_disk_template").lang("mustache").params(params).build();
|
||||
SearchRequest request = client().prepareSearch().setSearchType(ExecutableSearchTransform.DEFAULT_SEARCH_TYPE)
|
||||
.setIndices("test-search-index").request();
|
||||
|
||||
|
@ -504,7 +503,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
timeValueSeconds(5));
|
||||
}
|
||||
|
||||
private SearchTransform.Result executeSearchTransform(SearchRequest request, Script template, WatchExecutionContext ctx)
|
||||
private SearchTransform.Result executeSearchTransform(SearchRequest request, WatcherScript template, WatchExecutionContext ctx)
|
||||
throws IOException {
|
||||
createIndex("test-search-index");
|
||||
ensureGreen("test-search-index");
|
||||
|
@ -519,15 +518,15 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
protected WatcherSearchTemplateService watcherSearchTemplateService() {
|
||||
String master = internalCluster().getMasterName();
|
||||
return new WatcherSearchTemplateService(internalCluster().clusterService(master).getSettings(),
|
||||
ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class, master)),
|
||||
internalCluster().getInstance(ScriptService.class, master),
|
||||
internalCluster().getInstance(IndicesQueriesRegistry.class, master),
|
||||
internalCluster().getInstance(AggregatorParsers.class, master),
|
||||
internalCluster().getInstance(Suggesters.class, master)
|
||||
);
|
||||
}
|
||||
|
||||
protected ScriptServiceProxy scriptService() {
|
||||
return ScriptServiceProxy.of(internalCluster().getInstance(ScriptService.class));
|
||||
protected ScriptService scriptService() {
|
||||
return internalCluster().getInstance(ScriptService.class);
|
||||
}
|
||||
|
||||
private static Map<String, Object> doc(String date, String value) {
|
||||
|
@ -551,7 +550,7 @@ public class SearchTransformIT extends ESIntegTestCase {
|
|||
|
||||
@Override
|
||||
public ScriptContext.Plugin getCustomScriptContexts() {
|
||||
return ScriptServiceProxy.INSTANCE;
|
||||
return WatcherScript.CTX_PLUGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,13 @@ package org.elasticsearch.messy.tests;
|
|||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.search.SearchPhaseExecutionException;
|
||||
import org.elasticsearch.action.search.SearchResponse;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.indices.TermsLookup;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.script.Template;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.mustache.MustachePlugin;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.script.mustache.TemplateQueryBuilder;
|
||||
import org.elasticsearch.test.SecurityIntegTestCase;
|
||||
import org.elasticsearch.test.SecuritySettingsSource;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
|
@ -25,7 +24,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collection;
|
||||
|
||||
import static java.util.Collections.singletonMap;
|
||||
import static org.elasticsearch.script.ScriptService.ScriptType.INLINE;
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
@ -109,7 +107,7 @@ public class SecurityCachePermissionIT extends SecurityIntegTestCase {
|
|||
|
||||
//Template template = new Template(source, INLINE, MustacheScriptEngineService.NAME, null, singletonMap("name", "token"));
|
||||
SearchResponse response = client().prepareSearch("data").setTypes("a")
|
||||
.setQuery(QueryBuilders.templateQuery(source, singletonMap("name", "token")))
|
||||
.setQuery(new TemplateQueryBuilder(source, ScriptService.ScriptType.INLINE, singletonMap("name", "token")))
|
||||
.execute().actionGet();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
assertThat(response.getHits().hits().length, is(1));
|
||||
|
@ -119,7 +117,7 @@ public class SecurityCachePermissionIT extends SecurityIntegTestCase {
|
|||
.filterWithHeader(singletonMap("Authorization", basicAuthHeaderValue(READ_ONE_IDX_USER,
|
||||
new SecuredString("changeme".toCharArray()))))
|
||||
.prepareSearch("data").setTypes("a")
|
||||
.setQuery(QueryBuilders.templateQuery(source, singletonMap("name", "token")))
|
||||
.setQuery(new TemplateQueryBuilder(source, ScriptService.ScriptType.INLINE, singletonMap("name", "token")))
|
||||
.execute().actionGet());
|
||||
assertThat(e.toString(), containsString("ElasticsearchSecurityException[action"));
|
||||
assertThat(e.toString(), containsString("unauthorized"));
|
||||
|
|
|
@ -158,7 +158,7 @@ public class WatchAckIT extends AbstractWatcherIntegrationTestCase {
|
|||
assertThat(parsedWatch.status().actionStatus("_a2").ackStatus().state(),
|
||||
is(ActionStatus.AckStatus.State.AWAITS_SUCCESSFUL_EXECUTION));
|
||||
|
||||
long throttledCount = docCount(HistoryStore.INDEX_PREFIX + "*", null,
|
||||
long throttledCount = docCount(HistoryStore.INDEX_PREFIX_WITH_TEMPLATE + "*", null,
|
||||
matchQuery(WatchRecord.Field.STATE.getPreferredName(), ExecutionState.THROTTLED.id()));
|
||||
assertThat(throttledCount, greaterThan(0L));
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ public class WatchAckIT extends AbstractWatcherIntegrationTestCase {
|
|||
assertThat(parsedWatch.status().actionStatus("_a2").ackStatus().state(),
|
||||
is(ActionStatus.AckStatus.State.AWAITS_SUCCESSFUL_EXECUTION));
|
||||
|
||||
long throttledCount = docCount(HistoryStore.INDEX_PREFIX + "*", null,
|
||||
long throttledCount = docCount(HistoryStore.INDEX_PREFIX_WITH_TEMPLATE + "*", null,
|
||||
matchQuery(WatchRecord.Field.STATE.getPreferredName(), ExecutionState.THROTTLED.id()));
|
||||
assertThat(throttledCount, greaterThan(0L));
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ dependencies {
|
|||
integTest {
|
||||
cluster {
|
||||
setting 'script.inline', 'true'
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
[
|
||||
test_admin: 'superuser',
|
||||
|
|
|
@ -7,28 +7,29 @@ package org.elasticsearch.xpack.security;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class RestIT extends ESRestTestCase {
|
||||
public class ReindexWithSecurityClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
private static final String USER = "test_admin";
|
||||
private static final String PASS = "changeme";
|
||||
|
||||
public RestIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public ReindexWithSecurityClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
/**
|
|
@ -14,7 +14,7 @@ project.sourceSets.test.output.dir(outputDir, builtBy: copyXPackPluginProps)
|
|||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setupCommand 'setupDummyUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_user', '-p', 'changeme', '-r', 'superuser'
|
||||
setupCommand 'setupTransportClientUser',
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.elasticsearch.client.transport.TransportClient;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.transport.MockTransportClient;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
|
@ -115,6 +116,6 @@ public class SecurityTransportClientIT extends ESIntegTestCase {
|
|||
.put("cluster.name", clusterName)
|
||||
.build();
|
||||
|
||||
return TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build().addTransportAddress(publishAddress);
|
||||
return new MockTransportClient(settings, XPackPlugin.class).addTransportAddress(publishAddress);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ task buildZip(type:Zip, dependsOn: [jar]) {
|
|||
|
||||
task integTest(type: org.elasticsearch.gradle.test.RestIntegTestTask, dependsOn: buildZip) {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.authc.realms.custom.order', '0'
|
||||
setting 'xpack.security.authc.realms.custom.type', 'custom'
|
||||
setting 'xpack.security.authc.realms.esusers.order', '1'
|
||||
|
|
|
@ -7,14 +7,27 @@ package org.elasticsearch.example;
|
|||
|
||||
import org.elasticsearch.example.realm.CustomAuthenticationFailureHandler;
|
||||
import org.elasticsearch.example.realm.CustomRealm;
|
||||
import org.elasticsearch.example.realm.CustomRealmFactory;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationModule;
|
||||
import org.elasticsearch.xpack.security.authc.AuthenticationFailureHandler;
|
||||
import org.elasticsearch.xpack.extensions.XPackExtension;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class ExampleRealmExtension extends XPackExtension {
|
||||
|
||||
static {
|
||||
// check that the extension's policy works.
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
System.getSecurityManager().checkPrintJobAccess();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return "custom realm example";
|
||||
|
@ -25,13 +38,18 @@ public class ExampleRealmExtension extends XPackExtension {
|
|||
return "a very basic implementation of a custom realm to validate it works";
|
||||
}
|
||||
|
||||
public void onModule(AuthenticationModule authenticationModule) {
|
||||
authenticationModule.addCustomRealm(CustomRealm.TYPE, CustomRealmFactory.class);
|
||||
authenticationModule.setAuthenticationFailureHandler(CustomAuthenticationFailureHandler.class);
|
||||
// check that the extension's policy works.
|
||||
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
|
||||
System.getSecurityManager().checkPrintJobAccess();
|
||||
return null;
|
||||
});
|
||||
@Override
|
||||
public Map<String, Realm.Factory> getRealms() {
|
||||
return Collections.singletonMap(CustomRealm.TYPE, CustomRealm::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthenticationFailureHandler getAuthenticationFailureHandler() {
|
||||
return new CustomAuthenticationFailureHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> getRestHeaders() {
|
||||
return Arrays.asList(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,12 @@ import org.elasticsearch.xpack.security.authc.RealmConfig;
|
|||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken;
|
||||
|
||||
public class CustomRealm extends Realm<UsernamePasswordToken> {
|
||||
public class CustomRealm extends Realm {
|
||||
|
||||
public static final String TYPE = "custom";
|
||||
|
||||
static final String USER_HEADER = "User";
|
||||
static final String PW_HEADER = "Password";
|
||||
public static final String USER_HEADER = "User";
|
||||
public static final String PW_HEADER = "Password";
|
||||
|
||||
static final String KNOWN_USER = "custom_user";
|
||||
static final String KNOWN_PW = "changeme";
|
||||
|
@ -46,7 +46,8 @@ public class CustomRealm extends Realm<UsernamePasswordToken> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public User authenticate(UsernamePasswordToken token) {
|
||||
public User authenticate(AuthenticationToken authToken) {
|
||||
UsernamePasswordToken token = (UsernamePasswordToken)authToken;
|
||||
final String actualUser = token.principal();
|
||||
if (KNOWN_USER.equals(actualUser) && SecuredString.constantTimeEquals(token.credentials(), KNOWN_PW)) {
|
||||
return new User(actualUser, ROLES);
|
||||
|
|
|
@ -1,30 +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.example.realm;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.xpack.security.authc.Realm;
|
||||
import org.elasticsearch.xpack.security.authc.RealmConfig;
|
||||
|
||||
public class CustomRealmFactory extends Realm.Factory<CustomRealm> {
|
||||
|
||||
@Inject
|
||||
public CustomRealmFactory(RestController controller) {
|
||||
super(CustomRealm.TYPE, false);
|
||||
controller.registerRelevantHeaders(CustomRealm.USER_HEADER, CustomRealm.PW_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRealm create(RealmConfig config) {
|
||||
return new CustomRealm(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomRealm createDefault(String name) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -20,7 +20,9 @@ import org.elasticsearch.env.Environment;
|
|||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -58,12 +60,11 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
}
|
||||
|
||||
public void testHttpAuthentication() throws Exception {
|
||||
try (Response response = getRestClient().performRequest("GET", "/",
|
||||
Response response = getRestClient().performRequest("GET", "/",
|
||||
new BasicHeader(CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER),
|
||||
new BasicHeader(CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW))) {
|
||||
new BasicHeader(CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW));
|
||||
assertThat(response.getStatusLine().getStatusCode(), is(200));
|
||||
}
|
||||
}
|
||||
|
||||
public void testTransportClient() throws Exception {
|
||||
NodesInfoResponse nodeInfos = client().admin().cluster().prepareNodesInfo().get();
|
||||
|
@ -78,7 +79,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER)
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
try (TransportClient client = TransportClient.builder().settings(settings).addPlugin(XPackPlugin.class).build()) {
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
ClusterHealthResponse response = client.admin().cluster().prepareHealth().execute().actionGet();
|
||||
assertThat(response.isTimedOut(), is(false));
|
||||
|
@ -98,7 +99,7 @@ public class CustomRealmIT extends ESIntegTestCase {
|
|||
.put(ThreadContext.PREFIX + "." + CustomRealm.USER_HEADER, CustomRealm.KNOWN_USER + randomAsciiOfLength(1))
|
||||
.put(ThreadContext.PREFIX + "." + CustomRealm.PW_HEADER, CustomRealm.KNOWN_PW)
|
||||
.build();
|
||||
try (TransportClient client = TransportClient.builder().addPlugin(XPackPlugin.class).settings(settings).build()) {
|
||||
try (TransportClient client = new XPackTransportClient(settings)) {
|
||||
client.addTransportAddress(publishAddress);
|
||||
client.admin().cluster().prepareHealth().execute().actionGet();
|
||||
fail("authentication failure should have resulted in a NoNodesAvailableException");
|
||||
|
|
|
@ -7,7 +7,7 @@ dependencies {
|
|||
integTest {
|
||||
cluster {
|
||||
setting 'script.inline', 'true'
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
[
|
||||
test_admin: 'superuser',
|
||||
|
|
|
@ -118,6 +118,13 @@ public class MigrateToolIT extends MigrateToolTestCase {
|
|||
String token = basicAuthHeaderValue("bob", new SecuredString("changeme".toCharArray()));
|
||||
// Create "index1" index and try to search from it as "bob"
|
||||
client.filterWithHeader(Collections.singletonMap("Authorization", token)).admin().indices().prepareCreate("index1").get();
|
||||
// Wait for the index to be ready so it doesn't fail if no shards are initialized
|
||||
client.admin().cluster().health(Requests.clusterHealthRequest("index1")
|
||||
.timeout(TimeValue.timeValueSeconds(30))
|
||||
.waitForYellowStatus()
|
||||
.waitForEvents(Priority.LANGUID)
|
||||
.waitForRelocatingShards(0))
|
||||
.actionGet();
|
||||
SearchResponse searchResp = client.filterWithHeader(Collections.singletonMap("Authorization", token)).prepareSearch("index1").get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,8 @@ import org.elasticsearch.common.logging.ESLoggerFactory;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.common.transport.TransportAddress;
|
||||
import org.elasticsearch.node.internal.InternalSettingsPreparer;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackTransportClient;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
|
@ -25,10 +24,8 @@ import org.junit.BeforeClass;
|
|||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static com.carrotsearch.randomizedtesting.RandomizedTest.randomAsciiOfLength;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
||||
/**
|
||||
|
@ -45,6 +42,7 @@ import static org.hamcrest.Matchers.notNullValue;
|
|||
* your test.
|
||||
*/
|
||||
@LuceneTestCase.SuppressSysoutChecks(bugUrl = "we log a lot on purpose")
|
||||
@ESIntegTestCase.SuppressLocalMode
|
||||
public abstract class MigrateToolTestCase extends LuceneTestCase {
|
||||
|
||||
/**
|
||||
|
@ -77,13 +75,9 @@ public abstract class MigrateToolTestCase extends LuceneTestCase {
|
|||
.put("client.transport.ignore_cluster_name", true)
|
||||
.put("path.home", tempDir)
|
||||
.put(Security.USER_SETTING.getKey(), "transport_user:changeme")
|
||||
.put("node.mode", "network") // we require network here!
|
||||
.build();
|
||||
|
||||
TransportClient.Builder transportClientBuilder = TransportClient.builder()
|
||||
.addPlugin(XPackPlugin.class)
|
||||
.settings(clientSettings);
|
||||
TransportClient client = transportClientBuilder.build().addTransportAddresses(transportAddresses);
|
||||
TransportClient client = new XPackTransportClient(clientSettings).addTransportAddresses(transportAddresses);
|
||||
|
||||
logger.info("--> Elasticsearch Java TransportClient started");
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ integTest {
|
|||
dependsOn copyGraphRestTests
|
||||
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
setupCommand 'setupTestAdminUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'superuser'
|
||||
|
|
|
@ -7,31 +7,31 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
|
||||
public class GraphWithSecurityIT extends ESRestTestCase {
|
||||
public class GraphWithSecurityIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String TEST_ADMIN_USERNAME = "test_admin";
|
||||
private static final String TEST_ADMIN_PASSWORD = "changeme";
|
||||
|
||||
public GraphWithSecurityIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public GraphWithSecurityIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
protected String[] getCredentials() {
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
package org.elasticsearch.smoketest;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -14,14 +15,14 @@ import static org.hamcrest.Matchers.containsString;
|
|||
|
||||
public class GraphWithSecurityInsufficientRoleIT extends GraphWithSecurityIT {
|
||||
|
||||
public GraphWithSecurityInsufficientRoleIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public GraphWithSecurityInsufficientRoleIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
public void test() throws IOException {
|
||||
try {
|
||||
super.test();
|
||||
fail();
|
||||
fail("should have failed because of missing role");
|
||||
} catch(AssertionError ae) {
|
||||
assertThat(ae.getMessage(), containsString("action [indices:data/read/xpack/graph/explore"));
|
||||
assertThat(ae.getMessage(), containsString("returned [403 Forbidden]"));
|
||||
|
|
|
@ -17,7 +17,7 @@ subprojects {
|
|||
|
||||
cluster {
|
||||
systemProperty 'es.logger.level', 'TRACE'
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.monitoring.collection.interval', '3s'
|
||||
extraConfigFile 'x-pack/roles.yml', '../roles.yml'
|
||||
setupCommand 'setupTestAdminUser',
|
||||
|
|
|
@ -7,27 +7,28 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
public class MonitoringWithSecurityInsufficientRoleIT extends ESRestTestCase {
|
||||
public class SmokeTestMonitoringWithSecurityClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public MonitoringWithSecurityInsufficientRoleIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public SmokeTestMonitoringWithSecurityClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -7,26 +7,27 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class MonitoringWithSecurityIT extends ESRestTestCase {
|
||||
public class SmokeTestMonitoringWithSecurityClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public MonitoringWithSecurityIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public SmokeTestMonitoringWithSecurityClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -147,7 +147,7 @@ processTestResources.dependsOn(
|
|||
ext.pluginsCount = 1 // we install xpack explicitly
|
||||
project.rootProject.subprojects.findAll { it.path.startsWith(':plugins:') }.each { subproj ->
|
||||
// need to get a non-decorated project object, so must re-lookup the project by path
|
||||
integTest.cluster.plugin(subproj.name, project(subproj.path))
|
||||
integTest.cluster.plugin(subproj.path)
|
||||
pluginsCount += 1
|
||||
}
|
||||
|
||||
|
@ -166,7 +166,7 @@ integTest {
|
|||
setting 'xpack.security.ssl.keystore.path', nodeKeystore.name
|
||||
setting 'xpack.security.ssl.keystore.password', 'keypass'
|
||||
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
|
||||
// copy keystores into config/
|
||||
extraConfigFile nodeKeystore.name, nodeKeystore
|
||||
|
|
|
@ -9,11 +9,12 @@ import org.elasticsearch.ElasticsearchException;
|
|||
import org.elasticsearch.action.admin.cluster.node.info.NodeInfo;
|
||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.network.NetworkModule;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.transport.InetSocketTransportAddress;
|
||||
import org.elasticsearch.plugins.Plugin;
|
||||
import org.elasticsearch.xpack.security.Security;
|
||||
import org.elasticsearch.xpack.security.transport.netty.SecurityNettyTransport;
|
||||
import org.elasticsearch.xpack.security.transport.netty3.SecurityNetty3Transport;
|
||||
import org.elasticsearch.test.ESIntegTestCase;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.junit.After;
|
||||
|
@ -49,7 +50,6 @@ public class SmokeTestMonitoringWithSecurityIT extends ESIntegTestCase {
|
|||
private static final String USER = "test_user";
|
||||
private static final String PASS = "changeme";
|
||||
private static final String KEYSTORE_PASS = "keypass";
|
||||
|
||||
private static final String MONITORING_PATTERN = ".monitoring-*";
|
||||
|
||||
@Override
|
||||
|
@ -61,9 +61,10 @@ public class SmokeTestMonitoringWithSecurityIT extends ESIntegTestCase {
|
|||
protected Settings externalClusterClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(Security.USER_SETTING.getKey(), USER + ":" + PASS)
|
||||
.put(SecurityNettyTransport.SSL_SETTING.getKey(), true)
|
||||
.put(SecurityNetty3Transport.SSL_SETTING.getKey(), true)
|
||||
.put("xpack.security.ssl.keystore.path", clientKeyStore)
|
||||
.put("xpack.security.ssl.keystore.password", KEYSTORE_PASS)
|
||||
.put(NetworkModule.TRANSPORT_TYPE_KEY, Security.NAME)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
|
|
@ -7,15 +7,16 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.io.PathUtils;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.client.RestTestClient;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
|
@ -26,19 +27,19 @@ import java.nio.file.Path;
|
|||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class SmokeTestPluginsSslIT extends ESRestTestCase {
|
||||
public class SmokeTestPluginsSslClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String USER = "test_user";
|
||||
private static final String PASS = "changeme";
|
||||
private static final String KEYSTORE_PASS = "keypass";
|
||||
|
||||
public SmokeTestPluginsSslIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public SmokeTestPluginsSslClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
static Path keyStore;
|
||||
|
@ -46,7 +47,7 @@ public class SmokeTestPluginsSslIT extends ESRestTestCase {
|
|||
@BeforeClass
|
||||
public static void getKeyStore() {
|
||||
try {
|
||||
keyStore = PathUtils.get(SmokeTestPluginsSslIT.class.getResource("/test-node.jks").toURI());
|
||||
keyStore = PathUtils.get(SmokeTestPluginsSslClientYamlTestSuiteIT.class.getResource("/test-node.jks").toURI());
|
||||
} catch (URISyntaxException e) {
|
||||
throw new ElasticsearchException("exception while reading the store", e);
|
||||
}
|
||||
|
@ -65,9 +66,13 @@ public class SmokeTestPluginsSslIT extends ESRestTestCase {
|
|||
String token = basicAuthHeaderValue(USER, new SecuredString(PASS.toCharArray()));
|
||||
return Settings.builder()
|
||||
.put(ThreadContext.PREFIX + ".Authorization", token)
|
||||
.put(RestTestClient.PROTOCOL, "https")
|
||||
.put(RestTestClient.TRUSTSTORE_PATH, keyStore)
|
||||
.put(RestTestClient.TRUSTSTORE_PASSWORD, KEYSTORE_PASS)
|
||||
.put(ESRestTestCase.TRUSTSTORE_PATH, keyStore)
|
||||
.put(ESRestTestCase.TRUSTSTORE_PASSWORD, KEYSTORE_PASS)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getProtocol() {
|
||||
return "https";
|
||||
}
|
||||
}
|
|
@ -9,13 +9,13 @@ dependencies {
|
|||
ext.pluginsCount = 1 // we install xpack explicitly
|
||||
project.rootProject.subprojects.findAll { it.path.startsWith(':plugins:') }.each { subproj ->
|
||||
// need to get a non-decorated project object, so must re-lookup the project by path
|
||||
integTest.cluster.plugin(subproj.name, project(subproj.path))
|
||||
integTest.cluster.plugin(subproj.path)
|
||||
pluginsCount += 1
|
||||
}
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
|
||||
setupCommand 'setupDummyUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_user', '-p', 'changeme', '-r', 'superuser'
|
||||
|
|
|
@ -7,29 +7,30 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class SmokeTestPluginsIT extends ESRestTestCase {
|
||||
public class XSmokeTestPluginsClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String USER = "test_user";
|
||||
private static final String PASS = "changeme";
|
||||
|
||||
public SmokeTestPluginsIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public XSmokeTestPluginsClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,27 @@
|
|||
apply plugin: 'elasticsearch.rest-test'
|
||||
|
||||
dependencies {
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime')
|
||||
testCompile project(path: ':modules:lang-mustache', configuration: 'runtime')
|
||||
}
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.watcher.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'path.scripts', "${project.buildDir}/resources/test/templates"
|
||||
setupCommand 'setupDummyUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'superuser'
|
||||
waitCondition = { node, ant ->
|
||||
File tmpFile = new File(node.cwd, 'wait.success')
|
||||
ant.get(src: "http://${node.httpUri()}",
|
||||
dest: tmpFile.toString(),
|
||||
username: 'test_admin',
|
||||
password: 'changeme',
|
||||
ignoreerrors: true,
|
||||
retries: 10)
|
||||
return tmpFile.exists()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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.smoketest;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
public class SmokeTestSecurityWithMustacheClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("test_admin", new SecuredString("changeme".toCharArray()));
|
||||
|
||||
public SmokeTestSecurityWithMustacheClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Settings restClientSettings() {
|
||||
return Settings.builder()
|
||||
.put(ThreadContext.PREFIX + ".Authorization", BASIC_AUTH_VALUE)
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,191 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "inline_template_user"
|
||||
body: >
|
||||
{
|
||||
"password": "changeme",
|
||||
"roles" : [ "inline_template_role" ]
|
||||
}
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "stored_template_user"
|
||||
body: >
|
||||
{
|
||||
"password": "changeme",
|
||||
"roles" : [ "stored_template_role" ]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "file_template_user"
|
||||
body: >
|
||||
{
|
||||
"password": "changeme",
|
||||
"roles" : [ "file_template_role" ]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "inline_template_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{
|
||||
"names": "foobar",
|
||||
"privileges": ["all"],
|
||||
"query" : {
|
||||
"template" : {
|
||||
"inline" : {
|
||||
"term" : { "username" : "{{_user.username}}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "stored_template_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{
|
||||
"names": "foobar",
|
||||
"privileges": ["all"],
|
||||
"query" : {
|
||||
"template" : {
|
||||
"id" : "1"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "file_template_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{
|
||||
"names": "foobar",
|
||||
"privileges": ["all"],
|
||||
"query" : {
|
||||
"template" : {
|
||||
"file" : "query"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
put_template:
|
||||
id: "1"
|
||||
body: >
|
||||
{
|
||||
"term" : {
|
||||
"username" : "{{_user.username}}"
|
||||
}
|
||||
}
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: foobar
|
||||
type: type
|
||||
id: 1
|
||||
body: >
|
||||
{
|
||||
"username": "inline_template_user"
|
||||
}
|
||||
- do:
|
||||
index:
|
||||
index: foobar
|
||||
type: type
|
||||
id: 2
|
||||
body: >
|
||||
{
|
||||
"username": "stored_template_user"
|
||||
}
|
||||
- do:
|
||||
index:
|
||||
index: foobar
|
||||
type: type
|
||||
id: 3
|
||||
body: >
|
||||
{
|
||||
"username": "file_template_user"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
---
|
||||
teardown:
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "inline_template_user"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "stored_template_user"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "file_template_user"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "inline_template_role"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "stored_template_role"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "file_template_role"
|
||||
ignore: 404
|
||||
|
||||
---
|
||||
"Test inline template":
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic aW5saW5lX3RlbXBsYXRlX3VzZXI6Y2hhbmdlbWU="
|
||||
search:
|
||||
index: foobar
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.username: inline_template_user}
|
||||
|
||||
---
|
||||
"Test stored template":
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic c3RvcmVkX3RlbXBsYXRlX3VzZXI6Y2hhbmdlbWU="
|
||||
search:
|
||||
index: foobar
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.username: stored_template_user}
|
||||
|
||||
---
|
||||
"Test file template":
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic ZmlsZV90ZW1wbGF0ZV91c2VyOmNoYW5nZW1l"
|
||||
search:
|
||||
index: foobar
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.username: file_template_user}
|
|
@ -0,0 +1,198 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: headers
|
||||
|
||||
- do:
|
||||
indices.create:
|
||||
index: shared_logs
|
||||
|
||||
- do:
|
||||
cluster.health:
|
||||
wait_for_status: yellow
|
||||
- do:
|
||||
ingest.put_pipeline:
|
||||
id: "my_pipeline"
|
||||
body: >
|
||||
{
|
||||
"processors": [
|
||||
{
|
||||
"set_security_user" : {
|
||||
"field" : "user"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "joe"
|
||||
body: >
|
||||
{
|
||||
"password": "changeme",
|
||||
"roles" : [ "small_companies_role" ],
|
||||
"metadata" : {
|
||||
"customer_id" : "1"
|
||||
}
|
||||
}
|
||||
- do:
|
||||
xpack.security.put_user:
|
||||
username: "john"
|
||||
body: >
|
||||
{
|
||||
"password": "changeme",
|
||||
"roles" : [ "small_companies_role" ],
|
||||
"metadata" : {
|
||||
"customer_id" : "2"
|
||||
}
|
||||
}
|
||||
|
||||
---
|
||||
teardown:
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "joe"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_user:
|
||||
username: "john"
|
||||
ignore: 404
|
||||
- do:
|
||||
xpack.security.delete_role:
|
||||
name: "small_companies_role"
|
||||
ignore: 404
|
||||
|
||||
---
|
||||
"Test shared index seperating user by using DLS role query with user's username":
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "small_companies_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{
|
||||
"names": "shared_logs",
|
||||
"privileges": ["read", "create"],
|
||||
"query" : {
|
||||
"template" : {
|
||||
"inline" : {
|
||||
"term" : { "user.username" : "{{_user.username}}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9lOmNoYW5nZW1l"
|
||||
index:
|
||||
index: shared_logs
|
||||
type: type
|
||||
pipeline: "my_pipeline"
|
||||
body: >
|
||||
{
|
||||
"log": "Joe's first log entry"
|
||||
}
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9objpjaGFuZ2VtZQ=="
|
||||
index:
|
||||
index: shared_logs
|
||||
type: type
|
||||
pipeline: "my_pipeline"
|
||||
body: >
|
||||
{
|
||||
"log": "John's first log entry"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
# Joe searches:
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9lOmNoYW5nZW1l"
|
||||
search:
|
||||
index: shared_logs
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.user.username: joe}
|
||||
|
||||
# John searches:
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9objpjaGFuZ2VtZQ=="
|
||||
search:
|
||||
index: shared_logs
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.user.username: john}
|
||||
|
||||
---
|
||||
"Test shared index seperating user by using DLS role query with user's metadata":
|
||||
- do:
|
||||
xpack.security.put_role:
|
||||
name: "small_companies_role"
|
||||
body: >
|
||||
{
|
||||
"indices": [
|
||||
{
|
||||
"names": "shared_logs",
|
||||
"privileges": ["read", "create"],
|
||||
"query" : {
|
||||
"template" : {
|
||||
"inline" : {
|
||||
"term" : { "user.metadata.customer_id" : "{{_user.metadata.customer_id}}" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9lOmNoYW5nZW1l"
|
||||
index:
|
||||
index: shared_logs
|
||||
type: type
|
||||
pipeline: "my_pipeline"
|
||||
body: >
|
||||
{
|
||||
"log": "Joe's first log entry"
|
||||
}
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9objpjaGFuZ2VtZQ=="
|
||||
index:
|
||||
index: shared_logs
|
||||
type: type
|
||||
pipeline: "my_pipeline"
|
||||
body: >
|
||||
{
|
||||
"log": "John's first log entry"
|
||||
}
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
# Joe searches:
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9lOmNoYW5nZW1l"
|
||||
search:
|
||||
index: shared_logs
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.user.username: joe}
|
||||
|
||||
# John searches:
|
||||
- do:
|
||||
headers:
|
||||
Authorization: "Basic am9objpjaGFuZ2VtZQ=="
|
||||
search:
|
||||
index: shared_logs
|
||||
body: { "query" : { "match_all" : {} } }
|
||||
- match: { hits.total: 1}
|
||||
- match: { hits.hits.0._source.user.username: john}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"term" : {
|
||||
"username" : "{{_user.username}}"
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ dependencies {
|
|||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'script.inline', 'true'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
|
|
|
@ -7,9 +7,10 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -18,15 +19,15 @@ import java.io.IOException;
|
|||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
public abstract class WatcherRestTestCase extends ESRestTestCase {
|
||||
public abstract class WatcherRestTestCase extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public WatcherRestTestCase(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public WatcherRestTestCase(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.smoketest;
|
||||
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
|
||||
/** Runs rest tests against external cluster */
|
||||
public class WatcherWithGroovyIT extends WatcherRestTestCase {
|
||||
|
||||
public WatcherWithGroovyIT(RestTestCandidate testCandidate) {
|
||||
public WatcherWithGroovyIT(ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
---
|
||||
"Test simple input to index action":
|
||||
- do:
|
||||
xpack.watcher.put_watch:
|
||||
id: my_watch
|
||||
body: >
|
||||
{
|
||||
"trigger" : { "schedule" : { "cron" : "0/1 * * * * ? 2020" } },
|
||||
"input" : { "simple" : { "foo": "bar" } },
|
||||
"actions" : {
|
||||
"index_action" : {
|
||||
"index" : {
|
||||
"index" : "idx",
|
||||
"doc_type" : "type",
|
||||
"execution_time_field" : "@timestamp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { _id: "my_watch" }
|
||||
|
||||
|
||||
- do:
|
||||
xpack.watcher.execute_watch:
|
||||
id: "my_watch"
|
||||
body: >
|
||||
{
|
||||
"trigger_data" : {
|
||||
"triggered_time" : "2016-07-07T09:00:00Z",
|
||||
"scheduled_time" : "2016-07-07T09:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
- match: { "watch_record.state": "executed" }
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: idx
|
||||
type: type
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._source.foo: bar }
|
||||
- gte: { hits.hits.0._source.@timestamp: '2016-07-08' }
|
||||
|
||||
---
|
||||
"Test simple input with document field":
|
||||
|
||||
- do:
|
||||
xpack.watcher.put_watch:
|
||||
id: my_watch
|
||||
body: >
|
||||
{
|
||||
"trigger" : { "schedule" : { "cron" : "0/1 * * * * ? 2020" } },
|
||||
"input" : { "simple" : { "foo": "bar" } },
|
||||
"actions" : {
|
||||
"index_action" : {
|
||||
"transform" : { "script" : { "inline": "return [ '_doc' : ctx.payload ]" } },
|
||||
"index" : {
|
||||
"index" : "idx",
|
||||
"doc_type" : "type",
|
||||
"execution_time_field" : "@timestamp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { _id: "my_watch" }
|
||||
|
||||
|
||||
- do:
|
||||
xpack.watcher.execute_watch:
|
||||
id: "my_watch"
|
||||
body: >
|
||||
{
|
||||
"trigger_data" : {
|
||||
"triggered_time" : "2016-07-07T09:00:00Z",
|
||||
"scheduled_time" : "2016-07-07T09:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
- match: { "watch_record.state": "executed" }
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: idx
|
||||
type: type
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
- match: { hits.hits.0._source.foo: bar }
|
||||
- gte: { hits.hits.0._source.@timestamp: '2016-07-08"' }
|
||||
|
||||
|
||||
---
|
||||
"Test simple input with wrong document results in error":
|
||||
|
||||
- do:
|
||||
xpack.watcher.put_watch:
|
||||
id: my_watch
|
||||
body: >
|
||||
{
|
||||
"trigger" : { "schedule" : { "cron" : "0/1 * * * * ? 2020" } },
|
||||
"input" : { "simple" : { "foo": "bar" } },
|
||||
"actions" : {
|
||||
"index_action" : {
|
||||
"transform" : { "script" : { "inline": "return [ '_doc' : 1 ]" } },
|
||||
"index" : {
|
||||
"index" : "idx",
|
||||
"doc_type" : "type",
|
||||
"execution_time_field" : "@timestamp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { _id: "my_watch" }
|
||||
|
||||
|
||||
- do:
|
||||
xpack.watcher.execute_watch:
|
||||
id: "my_watch"
|
||||
body: >
|
||||
{
|
||||
"record_execution" : true,
|
||||
"trigger_data" : {
|
||||
"triggered_time" : "2016-07-07T09:00:00Z",
|
||||
"scheduled_time" : "2016-07-07T09:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
- match: { "watch_record.state": "executed" }
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
indices.exists:
|
||||
index: idx
|
||||
|
||||
- is_false: ''
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: .watcher-history-*
|
||||
type: watch_record
|
||||
body: >
|
||||
{
|
||||
"query" : {
|
||||
"match" : {
|
||||
"result.actions.status": "failure"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { hits.total: 1 }
|
||||
|
||||
---
|
||||
"Test search input to index action with aggs":
|
||||
|
||||
- do:
|
||||
bulk:
|
||||
refresh: true
|
||||
body:
|
||||
- '{"index": {"_index": "idx", "_type": "type", "_id": "1"}}'
|
||||
- '{"@timestamp": "2016-07-07" }'
|
||||
- '{"index": {"_index": "idx", "_type": "type", "_id": "2"}}'
|
||||
- '{"@timestamp": "2016-07-08" }'
|
||||
- '{"index": {"_index": "idx", "_type": "type", "_id": "3"}}'
|
||||
- '{"@timestamp": "2016-07-09" }'
|
||||
|
||||
- do:
|
||||
xpack.watcher.put_watch:
|
||||
id: my_watch
|
||||
body: >
|
||||
{
|
||||
"trigger" : { "schedule" : { "cron" : "0/1 * * * * ? 2020" } },
|
||||
"input" : {
|
||||
"search" : {
|
||||
"request": {
|
||||
"indices" : [ "idx" ],
|
||||
"types" : [ "type" ],
|
||||
"body" : {
|
||||
"aggs" : {
|
||||
"trend" : {
|
||||
"date_histogram" : {
|
||||
"field" : "@timestamp",
|
||||
"interval" : "day"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"actions" : {
|
||||
"index_action" : {
|
||||
"transform" : { "script" : { "inline": "return [ '_doc' : ctx.payload.aggregations.trend.buckets]" } },
|
||||
"index" : {
|
||||
"index" : "idx",
|
||||
"doc_type" : "bucket",
|
||||
"execution_time_field" : "@timestamp"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- match: { _id: "my_watch" }
|
||||
|
||||
|
||||
- do:
|
||||
xpack.watcher.execute_watch:
|
||||
id: "my_watch"
|
||||
body: >
|
||||
{
|
||||
"trigger_data" : {
|
||||
"triggered_time" : "2016-07-07T09:00:00Z",
|
||||
"scheduled_time" : "2016-07-07T09:00:00Z"
|
||||
}
|
||||
}
|
||||
|
||||
- match: { "watch_record.state": "executed" }
|
||||
|
||||
- do:
|
||||
indices.refresh: {}
|
||||
|
||||
- do:
|
||||
search:
|
||||
index: idx
|
||||
type: bucket
|
||||
|
||||
- match: { hits.total: 3 }
|
||||
|
|
@ -7,7 +7,7 @@ dependencies {
|
|||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'http.port', '9400'
|
||||
|
|
|
@ -7,9 +7,10 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -18,15 +19,15 @@ import java.io.IOException;
|
|||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
public abstract class WatcherRestTestCase extends ESRestTestCase {
|
||||
public abstract class SmokeTestWatchesWithMustacheClientYamlTestSuiteTestCase extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public WatcherRestTestCase(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public SmokeTestWatchesWithMustacheClientYamlTestSuiteTestCase(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Before
|
|
@ -6,37 +6,31 @@
|
|||
package org.elasticsearch.smoketest;
|
||||
|
||||
import com.fasterxml.jackson.core.io.JsonStringEncoder;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.script.ScriptContextRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineRegistry;
|
||||
import org.elasticsearch.script.ScriptEngineService;
|
||||
import org.elasticsearch.script.ScriptService;
|
||||
import org.elasticsearch.script.ScriptSettings;
|
||||
import org.elasticsearch.script.mustache.MustacheScriptEngineService;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.common.ScriptServiceProxy;
|
||||
import org.elasticsearch.xpack.common.text.DefaultTextTemplateEngine;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplate;
|
||||
import org.elasticsearch.xpack.common.text.TextTemplateEngine;
|
||||
import org.elasticsearch.xpack.watcher.support.WatcherScript;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
|
@ -50,7 +44,7 @@ public class WatcherTemplateTests extends ESTestCase {
|
|||
Settings setting = Settings.builder().put(ScriptService.SCRIPT_AUTO_RELOAD_ENABLED_SETTING, true).build();
|
||||
Environment environment = Mockito.mock(Environment.class);
|
||||
ResourceWatcherService resourceWatcherService = Mockito.mock(ResourceWatcherService.class);
|
||||
ScriptContextRegistry registry = new ScriptContextRegistry(Collections.singletonList(ScriptServiceProxy.INSTANCE));
|
||||
ScriptContextRegistry registry = new ScriptContextRegistry(Collections.singletonList(WatcherScript.CTX_PLUGIN));
|
||||
|
||||
ScriptEngineRegistry scriptEngineRegistry = new ScriptEngineRegistry(
|
||||
Collections.singleton(new MustacheScriptEngineService(setting))
|
||||
|
@ -58,7 +52,7 @@ public class WatcherTemplateTests extends ESTestCase {
|
|||
ScriptSettings scriptSettings = new ScriptSettings(scriptEngineRegistry, registry);
|
||||
ScriptService scriptService = new ScriptService(setting, environment, resourceWatcherService, scriptEngineRegistry,
|
||||
registry, scriptSettings);
|
||||
engine = new DefaultTextTemplateEngine(Settings.EMPTY, ScriptServiceProxy.of(scriptService));
|
||||
engine = new DefaultTextTemplateEngine(Settings.EMPTY, scriptService);
|
||||
}
|
||||
|
||||
public void testEscaping() throws Exception {
|
||||
|
|
|
@ -7,22 +7,23 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** Runs rest tests against external cluster */
|
||||
public class WatcherWithMustacheIT extends WatcherRestTestCase {
|
||||
public class WatcherWithMustacheIT extends SmokeTestWatchesWithMustacheClientYamlTestSuiteTestCase {
|
||||
|
||||
public WatcherWithMustacheIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public WatcherWithMustacheIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ dependencies {
|
|||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'script.inline', 'true'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
|
|
|
@ -7,9 +7,10 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
|
@ -18,15 +19,15 @@ import java.io.IOException;
|
|||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
public abstract class WatcherRestTestCase extends ESRestTestCase {
|
||||
public abstract class WatcherRestTestCase extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public WatcherRestTestCase(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public WatcherRestTestCase(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Before
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
*/
|
||||
package org.elasticsearch.smoketest;
|
||||
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
|
||||
/** Runs rest tests against external cluster */
|
||||
public class WatcherWithPainlessIT extends WatcherRestTestCase {
|
||||
|
||||
public WatcherWithPainlessIT(RestTestCandidate testCandidate) {
|
||||
public WatcherWithPainlessIT(ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ integTest {
|
|||
'getting_started/10_monitor_cluster_health/Getting started - Monitor cluster health'].join(',')
|
||||
|
||||
cluster {
|
||||
plugin 'x-pack', project(':x-plugins:elasticsearch:x-pack')
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
extraConfigFile 'x-pack/roles.yml', 'roles.yml'
|
||||
setupCommand 'setupTestAdminUser',
|
||||
'bin/x-pack/users', 'useradd', 'test_admin', '-p', 'changeme', '-r', 'superuser'
|
||||
|
|
|
@ -7,36 +7,35 @@ package org.elasticsearch.smoketest;
|
|||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.elasticsearch.xpack.security.authc.support.SecuredString;
|
||||
import org.elasticsearch.test.rest.ESRestTestCase;
|
||||
import org.elasticsearch.test.rest.RestTestCandidate;
|
||||
import org.elasticsearch.test.rest.parser.RestTestParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
import static org.elasticsearch.xpack.security.authc.support.UsernamePasswordToken.basicAuthHeaderValue;
|
||||
|
||||
|
||||
public class WatcherWithSecurityIT extends ESRestTestCase {
|
||||
public class SmokeTestWatcherWithSecurityClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
private static final String TEST_ADMIN_USERNAME = "test_admin";
|
||||
private static final String TEST_ADMIN_PASSWORD = "changeme";
|
||||
|
||||
public WatcherWithSecurityIT(@Name("yaml") RestTestCandidate testCandidate) {
|
||||
public SmokeTestWatcherWithSecurityClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, RestTestParseException {
|
||||
return ESRestTestCase.createParameters(0, 1);
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Before
|
|
@ -0,0 +1,14 @@
|
|||
apply plugin: 'elasticsearch.rest-test'
|
||||
|
||||
dependencies {
|
||||
testCompile project(path: ':x-plugins:elasticsearch:x-pack', configuration: 'runtime')
|
||||
}
|
||||
|
||||
integTest {
|
||||
cluster {
|
||||
plugin ':x-plugins:elasticsearch:x-pack'
|
||||
setting 'xpack.security.enabled', 'false'
|
||||
setting 'xpack.monitoring.enabled', 'false'
|
||||
setting 'http.port', '9400'
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.smoketest;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Name;
|
||||
import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
||||
|
||||
import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate;
|
||||
import org.elasticsearch.test.rest.yaml.ESClientYamlSuiteTestCase;
|
||||
import org.elasticsearch.test.rest.yaml.parser.ClientYamlTestParseException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.emptyMap;
|
||||
|
||||
/** Runs rest tests against external cluster */
|
||||
public class SmokeTestWatcherClientYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
|
||||
|
||||
public SmokeTestWatcherClientYamlTestSuiteIT(@Name("yaml") ClientYamlTestCandidate testCandidate) {
|
||||
super(testCandidate);
|
||||
}
|
||||
|
||||
@ParametersFactory
|
||||
public static Iterable<Object[]> parameters() throws IOException, ClientYamlTestParseException {
|
||||
return ESClientYamlSuiteTestCase.createParameters(0, 1);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void startWatcher() throws Exception {
|
||||
getAdminExecutionContext().callApi("xpack.watcher.start", emptyMap(), emptyList(), emptyMap());
|
||||
}
|
||||
|
||||
@After
|
||||
public void stopWatcher() throws Exception {
|
||||
getAdminExecutionContext().callApi("xpack.watcher.stop", emptyMap(), emptyList(), emptyMap());
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
# This test has been moved out of the regular tests as it requires Elasticsearch to run on port 9400
|
||||
# That is a no-go for the clients testing, who could start Elasticsearch on arbitrary ports
|
||||
#
|
||||
---
|
||||
setup:
|
||||
- do:
|
|
@ -21,14 +21,20 @@ ext.compactProfile = 'full'
|
|||
|
||||
dependencyLicenses.enabled = false
|
||||
|
||||
licenseHeaders {
|
||||
approvedLicenses << 'BCrypt (BSD-like)'
|
||||
additionalLicense 'BCRYP', 'BCrypt (BSD-like)', 'Copyright (c) 2006 Damien Miller <djm@mindrot.org>'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// license deps
|
||||
compile project(':x-plugins:elasticsearch:license:base')
|
||||
testCompile project(':x-plugins:elasticsearch:license:licensor')
|
||||
|
||||
// security deps
|
||||
compile project(path: ':modules:transport-netty3', configuration: 'runtime')
|
||||
compile 'dk.brics.automaton:automaton:1.11-8'
|
||||
compile 'com.unboundid:unboundid-ldapsdk:2.3.8'
|
||||
compile 'com.unboundid:unboundid-ldapsdk:3.1.1'
|
||||
compile 'org.bouncycastle:bcprov-jdk15on:1.54'
|
||||
compile 'org.bouncycastle:bcpkix-jdk15on:1.54'
|
||||
testCompile 'com.google.jimfs:jimfs:1.1'
|
||||
|
@ -231,13 +237,6 @@ thirdPartyAudit.excludes = [
|
|||
'javax.activation.UnsupportedDataTypeException'
|
||||
]
|
||||
|
||||
// someone figure out what the x-plugins logic should be
|
||||
licenseHeaders.enabled = false
|
||||
|
||||
forbiddenApisMain {
|
||||
signaturesURLs += [file('signatures.txt').toURI().toURL()]
|
||||
}
|
||||
|
||||
modifyPom { MavenPom pom ->
|
||||
pom.withXml { XmlProvider xml ->
|
||||
// first find if we have dependencies at all, and grab the node
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.elasticsearch.action.ActionRequest;
|
|||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
|
@ -43,15 +44,9 @@ public class Graph extends Plugin implements ActionPlugin {
|
|||
}
|
||||
|
||||
public Collection<Module> createGuiceModules() {
|
||||
return Collections.singletonList(new GraphModule(enabled, transportClientMode));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Class<? extends LifecycleComponent>> getGuiceServiceClasses() {
|
||||
if (enabled == false|| transportClientMode) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList(GraphLicensee.class);
|
||||
return Collections.singletonList(b -> {
|
||||
XPackPlugin.bindFeatureSet(b, GraphFeatureSet.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.elasticsearch.common.inject.Inject;
|
|||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.xpack.XPackFeatureSet;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -20,12 +21,12 @@ import java.io.IOException;
|
|||
public class GraphFeatureSet implements XPackFeatureSet {
|
||||
|
||||
private final boolean enabled;
|
||||
private final GraphLicensee licensee;
|
||||
private final XPackLicenseState licenseState;
|
||||
|
||||
@Inject
|
||||
public GraphFeatureSet(Settings settings, @Nullable GraphLicensee licensee, NamedWriteableRegistry namedWriteableRegistry) {
|
||||
public GraphFeatureSet(Settings settings, @Nullable XPackLicenseState licenseState, NamedWriteableRegistry namedWriteableRegistry) {
|
||||
this.enabled = Graph.enabled(settings);
|
||||
this.licensee = licensee;
|
||||
this.licenseState = licenseState;
|
||||
namedWriteableRegistry.register(Usage.class, Usage.writeableName(Graph.NAME), Usage::new);
|
||||
}
|
||||
|
||||
|
@ -41,7 +42,7 @@ public class GraphFeatureSet implements XPackFeatureSet {
|
|||
|
||||
@Override
|
||||
public boolean available() {
|
||||
return licensee != null && licensee.isAvailable();
|
||||
return licenseState != null && licenseState.isGraphAllowed();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,71 +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.xpack.graph;
|
||||
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeComponent;
|
||||
import org.elasticsearch.license.plugin.core.LicenseState;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
|
||||
public class GraphLicensee extends AbstractLicenseeComponent<GraphLicensee> {
|
||||
|
||||
public static final String ID = Graph.NAME;
|
||||
|
||||
@Inject
|
||||
public GraphLicensee(Settings settings, LicenseeRegistry clientService) {
|
||||
super(settings, ID, clientService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] expirationMessages() {
|
||||
return new String[] {
|
||||
"Graph explore APIs are disabled"
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
switch (newLicense.operationMode()) {
|
||||
case BASIC:
|
||||
case STANDARD:
|
||||
case GOLD:
|
||||
if (currentLicense != null) {
|
||||
switch (currentLicense.operationMode()) {
|
||||
case TRIAL:
|
||||
case PLATINUM:
|
||||
return new String[] { "Graph will be disabled" };
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return Strings.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if Graph Exploration should be enabled.
|
||||
* <p>
|
||||
* Exploration is only disabled when the license has expired or if the mode is not:
|
||||
* <ul>
|
||||
* <li>{@link OperationMode#PLATINUM}</li>
|
||||
* <li>{@link OperationMode#TRIAL}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @return {@code true} as long as the license is valid. Otherwise {@code false}.
|
||||
*/
|
||||
public boolean isAvailable() {
|
||||
// status is volatile
|
||||
Status localStatus = status;
|
||||
OperationMode operationMode = localStatus.getMode();
|
||||
|
||||
boolean licensed = operationMode == OperationMode.TRIAL || operationMode == OperationMode.PLATINUM;
|
||||
|
||||
return licensed && localStatus.getLicenseState() != LicenseState.DISABLED;
|
||||
}
|
||||
}
|
|
@ -1,35 +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.xpack.graph;
|
||||
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.util.Providers;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class GraphModule extends AbstractModule {
|
||||
|
||||
private final boolean enabled;
|
||||
private final boolean transportClientNode;
|
||||
|
||||
public GraphModule(boolean enabled, boolean transportClientNode) {
|
||||
this.enabled = enabled;
|
||||
this.transportClientNode = transportClientNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
XPackPlugin.bindFeatureSet(binder(), GraphFeatureSet.class);
|
||||
if (enabled && transportClientNode == false) {
|
||||
bind(GraphLicensee.class).asEagerSingleton();
|
||||
} else {
|
||||
bind(GraphLicensee.class).toProvider(Providers.of(null));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -23,7 +23,8 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.common.util.CollectionUtils;
|
||||
import org.elasticsearch.index.query.BoolQueryBuilder;
|
||||
import org.elasticsearch.index.query.QueryBuilders;
|
||||
import org.elasticsearch.license.plugin.core.LicenseUtils;
|
||||
import org.elasticsearch.license.LicenseUtils;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilders;
|
||||
import org.elasticsearch.search.aggregations.AggregationBuilder;
|
||||
import org.elasticsearch.search.aggregations.bucket.sampler.DiversifiedAggregationBuilder;
|
||||
|
@ -37,7 +38,7 @@ import org.elasticsearch.search.aggregations.bucket.terms.support.IncludeExclude
|
|||
import org.elasticsearch.search.builder.SearchSourceBuilder;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
import org.elasticsearch.xpack.graph.GraphLicensee;
|
||||
import org.elasticsearch.xpack.graph.Graph;
|
||||
import org.elasticsearch.xpack.graph.action.Connection.ConnectionId;
|
||||
import org.elasticsearch.xpack.graph.action.GraphExploreRequest.TermBoost;
|
||||
import org.elasticsearch.xpack.graph.action.Vertex.VertexId;
|
||||
|
@ -58,7 +59,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
public class TransportGraphExploreAction extends HandledTransportAction<GraphExploreRequest, GraphExploreResponse> {
|
||||
|
||||
private final TransportSearchAction searchAction;
|
||||
protected final GraphLicensee licensee;
|
||||
protected final XPackLicenseState licenseState;
|
||||
|
||||
static class VertexPriorityQueue extends PriorityQueue<Vertex> {
|
||||
|
||||
|
@ -76,19 +77,19 @@ public class TransportGraphExploreAction extends HandledTransportAction<GraphExp
|
|||
@Inject
|
||||
public TransportGraphExploreAction(Settings settings, ThreadPool threadPool, TransportSearchAction transportSearchAction,
|
||||
TransportService transportService, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
GraphLicensee licensee) {
|
||||
XPackLicenseState licenseState) {
|
||||
super(settings, GraphExploreAction.NAME, threadPool, transportService, actionFilters, indexNameExpressionResolver,
|
||||
GraphExploreRequest::new);
|
||||
this.searchAction = transportSearchAction;
|
||||
this.licensee = licensee;
|
||||
this.licenseState = licenseState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doExecute(GraphExploreRequest request, ActionListener<GraphExploreResponse> listener) {
|
||||
if (licensee.isAvailable()) {
|
||||
if (licenseState.isGraphAllowed()) {
|
||||
new AsyncGraphAction(request, listener).start();
|
||||
} else {
|
||||
listener.onFailure(LicenseUtils.newComplianceException(GraphLicensee.ID));
|
||||
listener.onFailure(LicenseUtils.newComplianceException(Graph.NAME));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@ package org.elasticsearch.xpack.graph;
|
|||
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.XPackLicenseState;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.graph.GraphFeatureSet;
|
||||
import org.elasticsearch.xpack.graph.GraphLicensee;
|
||||
import org.junit.Before;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
|
@ -24,24 +23,24 @@ import static org.mockito.Mockito.when;
|
|||
*/
|
||||
public class GraphFeatureSetTests extends ESTestCase {
|
||||
|
||||
private GraphLicensee licensee;
|
||||
private XPackLicenseState licenseState;
|
||||
private NamedWriteableRegistry namedWriteableRegistry;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception {
|
||||
licensee = mock(GraphLicensee.class);
|
||||
licenseState = mock(XPackLicenseState.class);
|
||||
namedWriteableRegistry = mock(NamedWriteableRegistry.class);
|
||||
}
|
||||
|
||||
public void testWritableRegistration() throws Exception {
|
||||
new GraphFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry);
|
||||
new GraphFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry);
|
||||
verify(namedWriteableRegistry).register(eq(GraphFeatureSet.Usage.class), eq("xpack.usage.graph"), anyObject());
|
||||
}
|
||||
|
||||
public void testAvailable() throws Exception {
|
||||
GraphFeatureSet featureSet = new GraphFeatureSet(Settings.EMPTY, licensee, namedWriteableRegistry);
|
||||
GraphFeatureSet featureSet = new GraphFeatureSet(Settings.EMPTY, licenseState, namedWriteableRegistry);
|
||||
boolean available = randomBoolean();
|
||||
when(licensee.isAvailable()).thenReturn(available);
|
||||
when(licenseState.isGraphAllowed()).thenReturn(available);
|
||||
assertThat(featureSet.available(), is(available));
|
||||
}
|
||||
|
||||
|
@ -55,7 +54,7 @@ public class GraphFeatureSetTests extends ESTestCase {
|
|||
} else {
|
||||
settings.put("xpack.graph.enabled", enabled);
|
||||
}
|
||||
GraphFeatureSet featureSet = new GraphFeatureSet(settings.build(), licensee, namedWriteableRegistry);
|
||||
GraphFeatureSet featureSet = new GraphFeatureSet(settings.build(), licenseState, namedWriteableRegistry);
|
||||
assertThat(featureSet.enabled(), is(enabled));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,135 +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.xpack.graph.license;
|
||||
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.core.License.OperationMode;
|
||||
import org.elasticsearch.license.plugin.core.AbstractLicenseeTestCase;
|
||||
import org.elasticsearch.xpack.graph.GraphLicensee;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
public class LicenseTests extends AbstractLicenseeTestCase {
|
||||
|
||||
private SimpleLicenseeRegistry licenseeRegistry = new SimpleLicenseeRegistry();
|
||||
|
||||
public void testPlatinumTrialLicenseCanDoEverything() throws Exception {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testBasicLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testStandardLicenseIsDisabled() throws Exception {
|
||||
licenseeRegistry.setOperationMode(OperationMode.STANDARD);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testNoLicenseDoesNotWork() {
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testExpiredPlatinumTrialLicenseIsRestricted() throws Exception {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingFromBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToBasicLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(OperationMode.BASIC);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingFromStandardLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(OperationMode.STANDARD);
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToStandardLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(OperationMode.STANDARD);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testDowngradingToGoldLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(OperationMode.GOLD);
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
public void testUpgradingExpiredLicenseWorks() {
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
GraphLicensee graphLicensee = new GraphLicensee(Settings.EMPTY, licenseeRegistry);
|
||||
licenseeRegistry.register(graphLicensee);
|
||||
licenseeRegistry.disable();
|
||||
|
||||
assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(graphLicensee);
|
||||
|
||||
licenseeRegistry.setOperationMode(randomTrialOrPlatinumMode());
|
||||
assertLicensePlatinumTrialBehaviour(graphLicensee);
|
||||
}
|
||||
|
||||
private void assertLicensePlatinumTrialBehaviour(GraphLicensee graphLicensee) {
|
||||
assertThat("Expected graph exploration to be allowed", graphLicensee.isAvailable(), is(true));
|
||||
}
|
||||
|
||||
private void assertLicenseBasicOrStandardGoldOrNoneOrExpiredBehaviour(GraphLicensee graphLicensee) {
|
||||
assertThat("Expected graph exploration not to be allowed", graphLicensee.isAvailable(), is(false));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.delete;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.delete;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.master.AcknowledgedRequest;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.delete;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.delete;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.common.logging.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
@ -12,7 +12,7 @@ import org.elasticsearch.xpack.scheduler.SchedulerEngine;
|
|||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class ExpirationCallback {
|
||||
abstract class ExpirationCallback {
|
||||
|
||||
static final String EXPIRATION_JOB_PREFIX = ".license_expiration_job_";
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.get;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.get;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.get;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.support.master.MasterNodeReadOperationRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.get;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
|
@ -18,18 +18,18 @@ import org.elasticsearch.cluster.metadata.MetaData;
|
|||
import org.elasticsearch.common.Nullable;
|
||||
import org.elasticsearch.common.component.AbstractLifecycleComponent;
|
||||
import org.elasticsearch.common.component.Lifecycle;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.joda.FormatDateTimeFormatter;
|
||||
import org.elasticsearch.common.joda.Joda;
|
||||
import org.elasticsearch.common.logging.LoggerMessageFormat;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.gateway.GatewayService;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.core.LicenseVerifier;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.license.core.OperationModeFileWatcher;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.XPackPlugin;
|
||||
import org.elasticsearch.xpack.scheduler.SchedulerEngine;
|
||||
import org.elasticsearch.xpack.support.clock.Clock;
|
||||
|
||||
|
@ -40,41 +40,29 @@ import java.util.List;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Service responsible for managing {@link LicensesMetaData}
|
||||
* Interfaces through which this is exposed are:
|
||||
* - LicensesManagerService - responsible for managing signed and one-time-trial licenses
|
||||
* - LicensesClientService - responsible for listener registration of consumer plugin(s)
|
||||
* Service responsible for managing {@link LicensesMetaData}.
|
||||
* <p>
|
||||
* Registration Scheme:
|
||||
* <p>
|
||||
* A consumer plugin is registered with {@link LicenseeRegistry#register(Licensee)}
|
||||
* This method can be called at any time during the life-cycle of the consumer plugin.
|
||||
* If the listener can not be registered immediately, it is queued up and registered on the first clusterChanged event with
|
||||
* no {@link org.elasticsearch.gateway.GatewayService#STATE_NOT_RECOVERED_BLOCK} block
|
||||
* Upon successful registration, the listeners are notified appropriately using the notification scheme
|
||||
* <p>
|
||||
* Notification Scheme:
|
||||
* <p>
|
||||
* All registered listeners are notified of the current license upon registration or when a new license is installed in the cluster state.
|
||||
* When a new license is notified as enabled to the registered listener, a notification is scheduled at the time of license expiry.
|
||||
* Registered listeners are notified using {@link #onUpdate(LicensesMetaData)}
|
||||
* On the master node, the service handles updating the cluster state when a new license is registered.
|
||||
* It also listens on all nodes for cluster state updates, and updates {@link XPackLicenseState} when
|
||||
* the license changes are detected in the cluster state.
|
||||
*/
|
||||
public class LicensesService extends AbstractLifecycleComponent implements ClusterStateListener, LicensesManagerService,
|
||||
LicenseeRegistry, SchedulerEngine.Listener {
|
||||
public class LicenseService extends AbstractLifecycleComponent implements ClusterStateListener, SchedulerEngine.Listener {
|
||||
|
||||
// pkg private for tests
|
||||
static final TimeValue TRIAL_LICENSE_DURATION = TimeValue.timeValueHours(30 * 24);
|
||||
|
||||
/**
|
||||
* Duration of grace period after a license has expired
|
||||
*/
|
||||
static final TimeValue GRACE_PERIOD_DURATION = days(7);
|
||||
|
||||
private final ClusterService clusterService;
|
||||
|
||||
/**
|
||||
* Currently active consumers to notify to
|
||||
*/
|
||||
private final List<InternalLicensee> registeredLicensees = new CopyOnWriteArrayList<>();
|
||||
/** The xpack feature state to update when license changes are made. */
|
||||
private final XPackLicenseState licenseState;
|
||||
|
||||
/**
|
||||
* Currently active license
|
||||
|
@ -83,6 +71,11 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
private SchedulerEngine scheduler;
|
||||
private final Clock clock;
|
||||
|
||||
/**
|
||||
* File watcher for operation mode changes
|
||||
*/
|
||||
private final OperationModeFileWatcher operationModeFileWatcher;
|
||||
|
||||
/**
|
||||
* Callbacks to notify relative to license expiry
|
||||
*/
|
||||
|
@ -93,125 +86,78 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
*/
|
||||
private int trialLicenseMaxNodes = 1000;
|
||||
|
||||
/**
|
||||
* Duration of grace period after a license has expired
|
||||
*/
|
||||
public static final TimeValue GRACE_PERIOD_DURATION = days(7);
|
||||
|
||||
private static final String LICENSE_JOB = "licenseJob";
|
||||
public static final String LICENSE_JOB = "licenseJob";
|
||||
|
||||
private static final FormatDateTimeFormatter DATE_FORMATTER = Joda.forPattern("EEEE, MMMMM dd, yyyy", Locale.ROOT);
|
||||
|
||||
private static final String ACKNOWLEDGEMENT_HEADER = "This license update requires acknowledgement. To acknowledge the license, " +
|
||||
"please read the following messages and update the license again, this time with the \"acknowledge=true\" parameter:";
|
||||
|
||||
@Inject
|
||||
public LicensesService(Settings settings, ClusterService clusterService, Clock clock) {
|
||||
public LicenseService(Settings settings, ClusterService clusterService, Clock clock, Environment env,
|
||||
ResourceWatcherService resourceWatcherService, XPackLicenseState licenseState) {
|
||||
super(settings);
|
||||
this.clusterService = clusterService;
|
||||
populateExpirationCallbacks();
|
||||
this.clock = clock;
|
||||
this.scheduler = new SchedulerEngine(clock);
|
||||
this.licenseState = licenseState;
|
||||
this.operationModeFileWatcher = new OperationModeFileWatcher(resourceWatcherService,
|
||||
XPackPlugin.resolveConfigFile(env, "license_mode"), logger, () -> updateLicenseState(getLicense()));
|
||||
this.scheduler.register(this);
|
||||
populateExpirationCallbacks();
|
||||
}
|
||||
|
||||
private void logExpirationWarning(long expirationMillis, boolean expired) {
|
||||
String expiredMsg = expired ? "will expire" : "expired";
|
||||
String general = LoggerMessageFormat.format(null, "\n" +
|
||||
"#\n" +
|
||||
"# License [{}] on [{}]. If you have a new license, please update it.\n" +
|
||||
"# Otherwise, please reach out to your support contact.\n" +
|
||||
"# ", expiredMsg, DATE_FORMATTER.printer().print(expirationMillis));
|
||||
if (expired) {
|
||||
general = general.toUpperCase(Locale.ROOT);
|
||||
}
|
||||
StringBuilder builder = new StringBuilder(general);
|
||||
builder.append(System.lineSeparator());
|
||||
if (expired) {
|
||||
builder.append("# COMMERCIAL PLUGINS OPERATING WITH REDUCED FUNCTIONALITY");
|
||||
} else {
|
||||
builder.append("# Commercial plugins operate with reduced functionality on license expiration:");
|
||||
}
|
||||
XPackLicenseState.EXPIRATION_MESSAGES.forEach((feature, messages) -> {
|
||||
if (messages.length > 0) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(feature);
|
||||
for (String message : messages) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(message);
|
||||
}
|
||||
}
|
||||
});
|
||||
logger.warn("{}", builder);
|
||||
}
|
||||
|
||||
private void populateExpirationCallbacks() {
|
||||
expirationCallbacks.add(new ExpirationCallback.Pre(days(7), days(25), days(1)) {
|
||||
@Override
|
||||
public void on(License license) {
|
||||
String general = LoggerMessageFormat.format(null, "\n" +
|
||||
"#\n" +
|
||||
"# License will expire on [{}]. If you have a new license, please update it.\n" +
|
||||
"# Otherwise, please reach out to your support contact.\n" +
|
||||
"# ", DATE_FORMATTER.printer().print(license.expiryDate()));
|
||||
if (!registeredLicensees.isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder(general);
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# Commercial plugins operate with reduced functionality on license " +
|
||||
"expiration:");
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
if (licensee.expirationMessages().length > 0) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(licensee.id());
|
||||
for (String message : licensee.expirationMessages()) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(message);
|
||||
logExpirationWarning(license.expiryDate(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.warn("{}", builder);
|
||||
} else {
|
||||
logger.warn("{}", general);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
expirationCallbacks.add(new ExpirationCallback.Pre(days(0), days(7), TimeValue.timeValueMinutes(10)) {
|
||||
@Override
|
||||
public void on(License license) {
|
||||
String general = LoggerMessageFormat.format(null, "\n" +
|
||||
"#\n" +
|
||||
"# License will expire on [{}]. If you have a new license, please update it.\n" +
|
||||
"# Otherwise, please reach out to your support contact.\n" +
|
||||
"# ", DATE_FORMATTER.printer().print(license.expiryDate()));
|
||||
if (!registeredLicensees.isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder(general);
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# Commercial plugins operate with reduced functionality on license " +
|
||||
"expiration:");
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
if (licensee.expirationMessages().length > 0) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(licensee.id());
|
||||
for (String message : licensee.expirationMessages()) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(message);
|
||||
logExpirationWarning(license.expiryDate(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.warn("{}", builder.toString());
|
||||
} else {
|
||||
logger.warn("{}", general);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
expirationCallbacks.add(new ExpirationCallback.Post(days(0), null, TimeValue.timeValueMinutes(10)) {
|
||||
@Override
|
||||
public void on(License license) {
|
||||
// logged when grace period begins
|
||||
String general = LoggerMessageFormat.format(null, "\n" +
|
||||
"#\n" +
|
||||
"# LICENSE EXPIRED ON [{}]. IF YOU HAVE A NEW LICENSE, PLEASE\n" +
|
||||
"# UPDATE IT. OTHERWISE, PLEASE REACH OUT TO YOUR SUPPORT CONTACT.\n" +
|
||||
"# ", DATE_FORMATTER.printer().print(license.expiryDate()));
|
||||
if (!registeredLicensees.isEmpty()) {
|
||||
StringBuilder builder = new StringBuilder(general);
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# COMMERCIAL PLUGINS OPERATING WITH REDUCED FUNCTIONALITY");
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
if (licensee.expirationMessages().length > 0) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(licensee.id());
|
||||
for (String message : licensee.expirationMessages()) {
|
||||
builder.append(System.lineSeparator());
|
||||
builder.append("# - ");
|
||||
builder.append(message);
|
||||
logExpirationWarning(license.expiryDate(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.warn("{}", builder.toString());
|
||||
} else {
|
||||
logger.warn("{}", general);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,22 +173,23 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
listener.onResponse(new PutLicenseResponse(true, LicensesStatus.EXPIRED));
|
||||
} else {
|
||||
if (!request.acknowledged()) {
|
||||
// TODO: ack messages should be generated on the master, since another node's cluster state may be behind...
|
||||
final License currentLicense = getLicense();
|
||||
if (currentLicense != null) {
|
||||
Map<String, String[]> acknowledgeMessages = new HashMap<>(registeredLicensees.size() + 1);
|
||||
Map<String, String[]> acknowledgeMessages = new HashMap<>();
|
||||
if (!License.isAutoGeneratedLicense(currentLicense.signature()) // current license is not auto-generated
|
||||
&& currentLicense.issueDate() > newLicense.issueDate()) { // and has a later issue date
|
||||
acknowledgeMessages.put("license",
|
||||
new String[]{"The new license is older than the currently installed license. Are you sure you want to " +
|
||||
"override the current license?"});
|
||||
acknowledgeMessages.put("license", new String[]{
|
||||
"The new license is older than the currently installed license. " +
|
||||
"Are you sure you want to override the current license?"});
|
||||
}
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
String[] listenerAcknowledgeMessages = licensee.acknowledgmentMessages(currentLicense, newLicense);
|
||||
if (listenerAcknowledgeMessages.length > 0) {
|
||||
acknowledgeMessages.put(licensee.id(), listenerAcknowledgeMessages);
|
||||
XPackLicenseState.ACKNOWLEDGMENT_MESSAGES.forEach((feature, ackMessages) -> {
|
||||
String[] messages = ackMessages.apply(currentLicense.operationMode(), newLicense.operationMode());
|
||||
if (messages.length > 0) {
|
||||
acknowledgeMessages.put(feature, messages);
|
||||
}
|
||||
}
|
||||
if (!acknowledgeMessages.isEmpty()) {
|
||||
});
|
||||
if (acknowledgeMessages.isEmpty() == false) {
|
||||
// needs acknowledgement
|
||||
listener.onResponse(new PutLicenseResponse(false, LicensesStatus.VALID, ACKNOWLEDGEMENT_HEADER,
|
||||
acknowledgeMessages));
|
||||
|
@ -278,7 +225,7 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
if (licensesMetaData != null) {
|
||||
final License license = licensesMetaData.getLicense();
|
||||
if (event.getJobName().equals(LICENSE_JOB)) {
|
||||
notifyLicensees(license);
|
||||
updateLicenseState(license);
|
||||
} else if (event.getJobName().startsWith(ExpirationCallback.EXPIRATION_JOB_PREFIX)) {
|
||||
expirationCallbacks.stream()
|
||||
.filter(expirationCallback -> expirationCallback.getId().equals(event.getJobName()))
|
||||
|
@ -313,17 +260,6 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public LicenseState licenseState() {
|
||||
if (registeredLicensees.size() > 0) {
|
||||
return registeredLicensees.get(0).currentLicenseState;
|
||||
} else {
|
||||
final License license = getLicense(clusterService.state().metaData().custom(LicensesMetaData.TYPE));
|
||||
return getLicenseState(license, clock.millis());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public License getLicense() {
|
||||
final License license = getLicense(clusterService.state().metaData().custom(LicensesMetaData.TYPE));
|
||||
return license == LicensesMetaData.LICENSE_TOMBSTONE ? null : license;
|
||||
|
@ -377,15 +313,25 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
protected void doStart() throws ElasticsearchException {
|
||||
clusterService.add(this);
|
||||
scheduler.start(Collections.emptyList());
|
||||
logger.debug("initializing license state");
|
||||
final ClusterState clusterState = clusterService.state();
|
||||
if (clusterService.lifecycleState() == Lifecycle.State.STARTED
|
||||
&& clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false
|
||||
&& clusterState.nodes().getMasterNode() != null) {
|
||||
final LicensesMetaData currentMetaData = clusterState.metaData().custom(LicensesMetaData.TYPE);
|
||||
if (clusterState.getNodes().isLocalNodeElectedMaster() &&
|
||||
(currentMetaData == null || currentMetaData.getLicense() == null)) {
|
||||
// triggers a cluster changed event
|
||||
// eventually notifying the current licensee
|
||||
registerTrialLicense();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() throws ElasticsearchException {
|
||||
clusterService.remove(this);
|
||||
scheduler.stop();
|
||||
// clear all handlers
|
||||
registeredLicensees.clear();
|
||||
|
||||
// clear current license
|
||||
currentLicense.set(null);
|
||||
}
|
||||
|
@ -430,52 +376,28 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
}
|
||||
}
|
||||
|
||||
private void notifyLicensees(final License license) {
|
||||
protected void updateLicenseState(final License license) {
|
||||
if (license == LicensesMetaData.LICENSE_TOMBSTONE) {
|
||||
// implies license has been explicitly deleted
|
||||
// update licensee states
|
||||
registeredLicensees.forEach(InternalLicensee::onRemove);
|
||||
licenseState.update(License.OperationMode.MISSING, false);
|
||||
return;
|
||||
}
|
||||
if (license != null) {
|
||||
logger.debug("notifying [{}] listeners", registeredLicensees.size());
|
||||
switch (getLicenseState(license, clock.millis())) {
|
||||
case ENABLED:
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(license, LicenseState.ENABLED);
|
||||
}
|
||||
logger.debug("license [{}] - valid", license.uid());
|
||||
break;
|
||||
case GRACE_PERIOD:
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(license, LicenseState.GRACE_PERIOD);
|
||||
}
|
||||
logger.warn("license [{}] - grace", license.uid());
|
||||
break;
|
||||
case DISABLED:
|
||||
for (InternalLicensee licensee : registeredLicensees) {
|
||||
licensee.onChange(license, LicenseState.DISABLED);
|
||||
}
|
||||
logger.warn("license [{}] - expired", license.uid());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
long time = clock.millis();
|
||||
boolean active = time >= license.issueDate() &&
|
||||
time < license.expiryDate() + GRACE_PERIOD_DURATION.getMillis();
|
||||
licenseState.update(license.operationMode(), active);
|
||||
|
||||
static LicenseState getLicenseState(final License license, long time) {
|
||||
if (license == null) {
|
||||
return LicenseState.DISABLED;
|
||||
if (active) {
|
||||
if (time < license.expiryDate()) {
|
||||
logger.debug("license [{}] - valid", license.uid());
|
||||
} else {
|
||||
logger.warn("license [{}] - grace", license.uid());
|
||||
}
|
||||
if (license.issueDate() > time) {
|
||||
return LicenseState.DISABLED;
|
||||
} else {
|
||||
logger.warn("license [{}] - expired", license.uid());
|
||||
}
|
||||
if (license.expiryDate() > time) {
|
||||
return LicenseState.ENABLED;
|
||||
}
|
||||
if ((license.expiryDate() + GRACE_PERIOD_DURATION.getMillis()) > time) {
|
||||
return LicenseState.GRACE_PERIOD;
|
||||
}
|
||||
return LicenseState.DISABLED;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -489,42 +411,42 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
// license can be null if the trial license is yet to be auto-generated
|
||||
// in this case, it is a no-op
|
||||
if (license != null) {
|
||||
notifyLicensees(license);
|
||||
if (license.equals(currentLicense.get()) == false) {
|
||||
final License previousLicense = currentLicense.get();
|
||||
if (license.equals(previousLicense) == false) {
|
||||
currentLicense.set(license);
|
||||
scheduler.add(new SchedulerEngine.Job(LICENSE_JOB, new LicenseSchedule(license)));
|
||||
license.setOperationModeFileWatcher(operationModeFileWatcher);
|
||||
scheduler.add(new SchedulerEngine.Job(LICENSE_JOB, nextLicenseCheck(license)));
|
||||
for (ExpirationCallback expirationCallback : expirationCallbacks) {
|
||||
scheduler.add(new SchedulerEngine.Job(expirationCallback.getId(),
|
||||
(startTime, now) ->
|
||||
expirationCallback.nextScheduledTimeForExpiry(license.expiryDate(), startTime, now)));
|
||||
}
|
||||
if (previousLicense != null) {
|
||||
// remove operationModeFileWatcher to gc the old license object
|
||||
previousLicense.removeOperationModeFileWatcher();
|
||||
}
|
||||
}
|
||||
updateLicenseState(license);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(Licensee licensee) {
|
||||
for (final InternalLicensee existingLicensee : registeredLicensees) {
|
||||
if (existingLicensee.id().equals(licensee.id())) {
|
||||
throw new IllegalStateException("listener: [" + licensee.id() + "] has been already registered");
|
||||
}
|
||||
}
|
||||
logger.debug("registering licensee [{}]", licensee.id());
|
||||
registeredLicensees.add(new InternalLicensee(licensee));
|
||||
final ClusterState clusterState = clusterService.state();
|
||||
if (clusterService.lifecycleState() == Lifecycle.State.STARTED
|
||||
&& clusterState.blocks().hasGlobalBlock(GatewayService.STATE_NOT_RECOVERED_BLOCK) == false
|
||||
&& clusterState.nodes().getMasterNode() != null) {
|
||||
final LicensesMetaData currentMetaData = clusterState.metaData().custom(LicensesMetaData.TYPE);
|
||||
if (clusterState.getNodes().isLocalNodeElectedMaster() &&
|
||||
(currentMetaData == null || currentMetaData.getLicense() == null)) {
|
||||
// triggers a cluster changed event
|
||||
// eventually notifying the current licensee
|
||||
registerTrialLicense();
|
||||
} else if (lifecycleState() == Lifecycle.State.STARTED) {
|
||||
notifyLicensees(currentMetaData.getLicense());
|
||||
}
|
||||
// pkg private for tests
|
||||
static SchedulerEngine.Schedule nextLicenseCheck(License license) {
|
||||
return (startTime, time) -> {
|
||||
if (time < license.issueDate()) {
|
||||
// when we encounter a license with a future issue date
|
||||
// which can happen with autogenerated license,
|
||||
// we want to schedule a notification on the license issue date
|
||||
// so the license is notificed once it is valid
|
||||
// see https://github.com/elastic/x-plugins/issues/983
|
||||
return license.issueDate();
|
||||
} else if (time < license.expiryDate()) {
|
||||
return license.expiryDate();
|
||||
} else if (time < license.expiryDate() + GRACE_PERIOD_DURATION.getMillis()) {
|
||||
return license.expiryDate() + GRACE_PERIOD_DURATION.getMillis();
|
||||
}
|
||||
return -1; // license is expired, no need to check again
|
||||
};
|
||||
}
|
||||
|
||||
License getLicense(final LicensesMetaData metaData) {
|
||||
|
@ -532,7 +454,7 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
License license = metaData.getLicense();
|
||||
if (license == LicensesMetaData.LICENSE_TOMBSTONE) {
|
||||
return license;
|
||||
} else {
|
||||
} else if (license != null) {
|
||||
boolean autoGeneratedLicense = License.isAutoGeneratedLicense(license.signature());
|
||||
if ((autoGeneratedLicense && TrialLicense.verify(license))
|
||||
|| (!autoGeneratedLicense && LicenseVerifier.verifyLicense(license))) {
|
||||
|
@ -542,58 +464,4 @@ public class LicensesService extends AbstractLifecycleComponent implements Clust
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores acknowledgement, expiration and license notification callbacks
|
||||
* for a registered listener
|
||||
*/
|
||||
private class InternalLicensee {
|
||||
volatile License currentLicense = null;
|
||||
volatile LicenseState currentLicenseState = LicenseState.DISABLED;
|
||||
private final Licensee licensee;
|
||||
|
||||
private InternalLicensee(Licensee licensee) {
|
||||
this.licensee = licensee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "(listener: " + licensee.id() + ", state: " + currentLicenseState.name() + ")";
|
||||
}
|
||||
|
||||
public String id() {
|
||||
return licensee.id();
|
||||
}
|
||||
|
||||
public String[] expirationMessages() {
|
||||
return licensee.expirationMessages();
|
||||
}
|
||||
|
||||
public String[] acknowledgmentMessages(License currentLicense, License newLicense) {
|
||||
return licensee.acknowledgmentMessages(currentLicense, newLicense);
|
||||
}
|
||||
|
||||
public void onChange(License license, LicenseState state) {
|
||||
synchronized (this) {
|
||||
if (currentLicense == null // not yet initialized
|
||||
|| !currentLicense.equals(license) // current license has changed
|
||||
|| currentLicenseState != state) { // same license but state has changed
|
||||
logger.debug("licensee [{}] notified", licensee.id());
|
||||
licensee.onChange(new Licensee.Status(license.operationMode(), state));
|
||||
currentLicense = license;
|
||||
currentLicenseState = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onRemove() {
|
||||
synchronized (this) {
|
||||
if (currentLicense != null || currentLicenseState != LicenseState.DISABLED) {
|
||||
currentLicense = null;
|
||||
currentLicenseState = LicenseState.DISABLED;
|
||||
licensee.onChange(Licensee.Status.MISSING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchSecurityException;
|
||||
import org.elasticsearch.rest.RestStatus;
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.apache.lucene.util.CollectionUtil;
|
||||
import org.elasticsearch.Version;
|
||||
|
@ -32,7 +32,7 @@ import static org.elasticsearch.license.core.CryptUtils.encrypt;
|
|||
/**
|
||||
* Contains metadata about registered licenses
|
||||
*/
|
||||
public class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements MetaData.Custom {
|
||||
class LicensesMetaData extends AbstractDiffable<MetaData.Custom> implements MetaData.Custom {
|
||||
|
||||
public static final String TYPE = "licenses";
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
public enum LicensesStatus {
|
||||
VALID((byte) 0),
|
|
@ -3,37 +3,26 @@
|
|||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.license.plugin;
|
||||
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.component.LifecycleComponent;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.TransportDeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.TransportGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.TransportPutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.core.LicenseeRegistry;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.license.plugin.core.LicensesMetaData;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.license.plugin.rest.RestDeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.rest.RestGetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.rest.RestPutLicenseAction;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Module;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
import org.elasticsearch.rest.RestHandler;
|
||||
import org.elasticsearch.watcher.ResourceWatcherService;
|
||||
import org.elasticsearch.xpack.support.clock.Clock;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.elasticsearch.xpack.XPackPlugin.isTribeNode;
|
||||
import static org.elasticsearch.xpack.XPackPlugin.transportClientMode;
|
||||
|
@ -42,7 +31,8 @@ import static org.elasticsearch.xpack.XPackPlugin.transportClientMode;
|
|||
public class Licensing implements ActionPlugin {
|
||||
|
||||
public static final String NAME = "license";
|
||||
private final boolean isTransportClient;
|
||||
protected final Settings settings;
|
||||
protected final boolean isTransportClient;
|
||||
private final boolean isTribeNode;
|
||||
|
||||
static {
|
||||
|
@ -50,10 +40,15 @@ public class Licensing implements ActionPlugin {
|
|||
}
|
||||
|
||||
public Licensing(Settings settings) {
|
||||
this.settings = settings;
|
||||
isTransportClient = transportClientMode(settings);
|
||||
isTribeNode = isTribeNode(settings);
|
||||
}
|
||||
|
||||
public Collection<Module> nodeModules() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ActionHandler<? extends ActionRequest<?>, ? extends ActionResponse>> getActions() {
|
||||
if (isTribeNode) {
|
||||
|
@ -74,22 +69,12 @@ public class Licensing implements ActionPlugin {
|
|||
RestDeleteLicenseAction.class);
|
||||
}
|
||||
|
||||
public Collection<Class<? extends LifecycleComponent>> nodeServices() {
|
||||
if (isTransportClient == false && isTribeNode == false) {
|
||||
return Collections.<Class<? extends LifecycleComponent>>singletonList(LicensesService.class);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
public Collection<Module> nodeModules() {
|
||||
if (isTransportClient == false && isTribeNode == false) {
|
||||
return Collections.singletonList(b -> {
|
||||
b.bind(LicensesService.class).asEagerSingleton();
|
||||
b.bind(LicenseeRegistry.class).to(LicensesService.class);
|
||||
b.bind(LicensesManagerService.class).to(LicensesService.class);
|
||||
});
|
||||
}
|
||||
return Collections.emptyList();
|
||||
public Collection<Object> createComponents(ClusterService clusterService, Clock clock, Environment environment,
|
||||
ResourceWatcherService resourceWatcherService,
|
||||
XPackLicenseState licenseState) {
|
||||
LicenseService licenseService = new LicenseService(settings, clusterService, clock,
|
||||
environment, resourceWatcherService, licenseState);
|
||||
return Arrays.asList(licenseService, licenseState);
|
||||
}
|
||||
|
||||
public List<Setting<?>> getSettings() {
|
|
@ -3,23 +3,11 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.delete.DeleteLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequestBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
|
||||
/**
|
||||
*
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.put;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.put;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.ValidateActions;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.put;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.support.master.AcknowledgedRequestBuilder;
|
||||
import org.elasticsearch.client.ElasticsearchClient;
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.put;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -11,7 +11,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
|
|||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.license.plugin.core.LicensesStatus;
|
||||
import org.elasticsearch.license.LicensesStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.action.support.AcknowledgedRestListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
|
||||
|
||||
public class RestDeleteLicenseAction extends XPackRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestDeleteLicenseAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
// @deprecated Remove deprecations in 6.0
|
||||
controller.registerWithDeprecatedHandler(DELETE, URI_BASE + "/license", this,
|
||||
DELETE, "/_license", deprecationLogger);
|
||||
|
||||
// Remove _licenses support entirely in 6.0
|
||||
controller.registerAsDeprecatedHandler(DELETE, "/_licenses", this,
|
||||
"[DELETE /_licenses] is deprecated! Use " +
|
||||
"[DELETE /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final XPackClient client) {
|
||||
client.es().admin().cluster().execute(DeleteLicenseAction.INSTANCE,
|
||||
new DeleteLicenseRequest(),
|
||||
new AcknowledgedRestListener<>(channel));
|
||||
}
|
||||
}
|
|
@ -3,24 +3,21 @@
|
|||
* 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.rest;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.license.core.License;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.get.GetLicenseResponse;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
import org.elasticsearch.rest.RestRequest;
|
||||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -29,12 +26,20 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
|
|||
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
|
||||
import static org.elasticsearch.rest.RestStatus.OK;
|
||||
|
||||
public class RestGetLicenseAction extends BaseRestHandler {
|
||||
public class RestGetLicenseAction extends XPackRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestGetLicenseAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(GET, "/_xpack/license", this);
|
||||
// @deprecated Remove deprecations in 6.0
|
||||
controller.registerWithDeprecatedHandler(GET, URI_BASE + "/license", this,
|
||||
GET, "/_license", deprecationLogger);
|
||||
|
||||
// Remove _licenses support entirely in 6.0
|
||||
controller.registerAsDeprecatedHandler(GET, "/_licenses", this,
|
||||
"[GET /_licenses] is deprecated! Use " +
|
||||
"[GET /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,14 +49,14 @@ public class RestGetLicenseAction extends BaseRestHandler {
|
|||
* The licenses are sorted by latest issue_date
|
||||
*/
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final NodeClient client) {
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final XPackClient client) {
|
||||
final Map<String, String> overrideParams = new HashMap<>(2);
|
||||
overrideParams.put(License.REST_VIEW_MODE, "true");
|
||||
overrideParams.put(License.LICENSE_VERSION_MODE, String.valueOf(License.VERSION_CURRENT));
|
||||
final ToXContent.Params params = new ToXContent.DelegatingMapParams(overrideParams, request);
|
||||
GetLicenseRequest getLicenseRequest = new GetLicenseRequest();
|
||||
getLicenseRequest.local(request.paramAsBoolean("local", getLicenseRequest.local()));
|
||||
client.admin().cluster().execute(GetLicenseAction.INSTANCE, getLicenseRequest,
|
||||
client.es().admin().cluster().execute(GetLicenseAction.INSTANCE, getLicenseRequest,
|
||||
new RestBuilderListener<GetLicenseResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(GetLicenseResponse response, XContentBuilder builder) throws Exception {
|
|
@ -3,17 +3,12 @@
|
|||
* 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.rest;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseAction;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseRequest;
|
||||
import org.elasticsearch.license.plugin.action.put.PutLicenseResponse;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestChannel;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
|
@ -21,25 +16,40 @@ import org.elasticsearch.rest.RestRequest;
|
|||
import org.elasticsearch.rest.RestResponse;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.rest.action.support.RestBuilderListener;
|
||||
import org.elasticsearch.xpack.XPackClient;
|
||||
import org.elasticsearch.xpack.rest.XPackRestHandler;
|
||||
|
||||
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||
|
||||
public class RestPutLicenseAction extends BaseRestHandler {
|
||||
public class RestPutLicenseAction extends XPackRestHandler {
|
||||
|
||||
@Inject
|
||||
public RestPutLicenseAction(Settings settings, RestController controller) {
|
||||
super(settings);
|
||||
controller.registerHandler(PUT, "/_xpack/license", this);
|
||||
controller.registerHandler(POST, "/_xpack/license", this);
|
||||
// @deprecated Remove deprecations in 6.0
|
||||
controller.registerWithDeprecatedHandler(POST, URI_BASE + "/license", this,
|
||||
POST, "/_license", deprecationLogger);
|
||||
controller.registerWithDeprecatedHandler(PUT, URI_BASE + "/license", this,
|
||||
PUT, "/_license", deprecationLogger);
|
||||
|
||||
// Remove _licenses support entirely in 6.0
|
||||
controller.registerAsDeprecatedHandler(POST, "/_licenses", this,
|
||||
"[POST /_licenses] is deprecated! Use " +
|
||||
"[POST /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
controller.registerAsDeprecatedHandler(PUT, "/_licenses", this,
|
||||
"[PUT /_licenses] is deprecated! Use " +
|
||||
"[PUT /_xpack/license] instead.",
|
||||
deprecationLogger);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final NodeClient client) {
|
||||
public void handleRequest(final RestRequest request, final RestChannel channel, final XPackClient client) {
|
||||
PutLicenseRequest putLicenseRequest = new PutLicenseRequest();
|
||||
putLicenseRequest.license(request.content().utf8ToString());
|
||||
putLicenseRequest.acknowledge(request.paramAsBoolean("acknowledge", false));
|
||||
client.admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest,
|
||||
client.es().admin().cluster().execute(PutLicenseAction.INSTANCE, putLicenseRequest,
|
||||
new RestBuilderListener<PutLicenseResponse>(channel) {
|
||||
@Override
|
||||
public RestResponse buildResponse(PutLicenseResponse response, XContentBuilder builder) throws Exception {
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.delete;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
|
@ -17,21 +17,20 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
|||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
public class TransportDeleteLicenseAction extends TransportMasterNodeAction<DeleteLicenseRequest, DeleteLicenseResponse> {
|
||||
|
||||
private final LicensesService licensesService;
|
||||
private final LicenseService licenseService;
|
||||
|
||||
@Inject
|
||||
public TransportDeleteLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService,
|
||||
LicensesService licensesService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
LicenseService licenseService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, DeleteLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||
indexNameExpressionResolver, DeleteLicenseRequest::new);
|
||||
this.licensesService = licensesService;
|
||||
this.licenseService = licenseService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,7 +51,7 @@ public class TransportDeleteLicenseAction extends TransportMasterNodeAction<Dele
|
|||
@Override
|
||||
protected void masterOperation(final DeleteLicenseRequest request, ClusterState state, final ActionListener<DeleteLicenseResponse>
|
||||
listener) throws ElasticsearchException {
|
||||
licensesService.removeLicense(request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
licenseService.removeLicense(request, new ActionListener<ClusterStateUpdateResponse>() {
|
||||
@Override
|
||||
public void onResponse(ClusterStateUpdateResponse clusterStateUpdateResponse) {
|
||||
listener.onResponse(new DeleteLicenseResponse(clusterStateUpdateResponse.isAcknowledged()));
|
|
@ -3,34 +3,33 @@
|
|||
* 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.action.get;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesManagerService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
public class TransportGetLicenseAction extends TransportMasterNodeReadAction<GetLicenseRequest, GetLicenseResponse> {
|
||||
|
||||
private final LicensesManagerService licensesManagerService;
|
||||
private final LicenseService licenseService;
|
||||
|
||||
@Inject
|
||||
public TransportGetLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService,
|
||||
LicensesManagerService licensesManagerService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
LicenseService licenseService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, GetLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
|
||||
GetLicenseRequest::new);
|
||||
this.licensesManagerService = licensesManagerService;
|
||||
this.licenseService = licenseService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,6 +50,6 @@ public class TransportGetLicenseAction extends TransportMasterNodeReadAction<Get
|
|||
@Override
|
||||
protected void masterOperation(final GetLicenseRequest request, ClusterState state, final ActionListener<GetLicenseResponse>
|
||||
listener) throws ElasticsearchException {
|
||||
listener.onResponse(new GetLicenseResponse(licensesManagerService.getLicense()));
|
||||
listener.onResponse(new GetLicenseResponse(licenseService.getLicense()));
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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.action.put;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
|
@ -16,21 +16,20 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
|||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.common.inject.Inject;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.license.plugin.core.LicensesService;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
public class TransportPutLicenseAction extends TransportMasterNodeAction<PutLicenseRequest, PutLicenseResponse> {
|
||||
|
||||
private final LicensesService licensesService;
|
||||
private final LicenseService licenseService;
|
||||
|
||||
@Inject
|
||||
public TransportPutLicenseAction(Settings settings, TransportService transportService, ClusterService clusterService,
|
||||
LicensesService licensesService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
LicenseService licenseService, ThreadPool threadPool, ActionFilters actionFilters,
|
||||
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||
super(settings, PutLicenseAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
|
||||
PutLicenseRequest::new);
|
||||
this.licensesService = licensesService;
|
||||
this.licenseService = licenseService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -51,7 +50,7 @@ public class TransportPutLicenseAction extends TransportMasterNodeAction<PutLice
|
|||
@Override
|
||||
protected void masterOperation(final PutLicenseRequest request, ClusterState state, final ActionListener<PutLicenseResponse>
|
||||
listener) throws ElasticsearchException {
|
||||
licensesService.registerLicense(request, listener);
|
||||
licenseService.registerLicense(request, listener);
|
||||
}
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
* 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;
|
||||
package org.elasticsearch.license;
|
||||
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
|
@ -21,7 +21,7 @@ import java.util.Collections;
|
|||
import static org.elasticsearch.license.core.CryptUtils.decrypt;
|
||||
import static org.elasticsearch.license.core.CryptUtils.encrypt;
|
||||
|
||||
public class TrialLicense {
|
||||
class TrialLicense {
|
||||
|
||||
public static License create(License.Builder specBuilder) {
|
||||
License spec = specBuilder
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue