From 9bd2da86db01806c97529084861dfd1227be3ec9 Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Mon, 25 Sep 2017 16:01:18 +0200 Subject: [PATCH 1/9] [Tests] Reenable MonitoringIT Checking the size of the map doesn't make sense when each filter is checked independently right after. Original commit: elastic/x-pack-elasticsearch@58e5d3401d595bdd92a2e27f80b0ce44506a80d0 --- .../xpack/monitoring/integration/MonitoringIT.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/integration/MonitoringIT.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/integration/MonitoringIT.java index c803594bb05..493cc3344dd 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/integration/MonitoringIT.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/integration/MonitoringIT.java @@ -11,7 +11,6 @@ import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.nio.entity.NStringEntity; import org.apache.lucene.util.Constants; -import org.apache.lucene.util.LuceneTestCase; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.Version; import org.elasticsearch.client.Response; @@ -64,7 +63,6 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -@LuceneTestCase.AwaitsFix(bugUrl = "https://github.com/elastic/x-pack-elasticsearch/issues/2609") public class MonitoringIT extends ESRestTestCase { private static final String BASIC_AUTH_VALUE = basicAuthHeaderValue("x_pack_rest_user", TEST_PASSWORD_SECURE_STRING); @@ -411,9 +409,6 @@ public class MonitoringIT extends ESRestTestCase { final Map source = (Map) document.get("_source"); assertEquals(5, source.size()); - final Map nodeStats = (Map) source.get(NodeStatsMonitoringDoc.TYPE); - assertEquals(Constants.WINDOWS ? 8 : 9, nodeStats.size()); - NodeStatsMonitoringDoc.XCONTENT_FILTERS.forEach(filter -> { if (Constants.WINDOWS && filter.startsWith("node_stats.os.cpu.load_average")) { // load average is unavailable on Windows From 60996606432d26193bb74ee05b3c96b5a579a886 Mon Sep 17 00:00:00 2001 From: Tim Brooks Date: Mon, 25 Sep 2017 09:42:37 -0600 Subject: [PATCH 2/9] Update LicenseMetadata version check to be 6.1 This is related to elastic/x-pack-elasticsearch#1941. It modifies to the version check in LicenseMetadata because this elastic/x-pack-elasticsearch#2419 has been backported to 6.x. Original commit: elastic/x-pack-elasticsearch@052358b550eef11c98e50c2314acaefe5e7fb3ae --- .../java/org/elasticsearch/license/LicensesMetaData.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/plugin/src/main/java/org/elasticsearch/license/LicensesMetaData.java b/plugin/src/main/java/org/elasticsearch/license/LicensesMetaData.java index ff83de1e58a..d0a5b6e3307 100644 --- a/plugin/src/main/java/org/elasticsearch/license/LicensesMetaData.java +++ b/plugin/src/main/java/org/elasticsearch/license/LicensesMetaData.java @@ -160,8 +160,7 @@ class LicensesMetaData extends AbstractNamedDiffable implements streamOutput.writeBoolean(true); // has a license license.writeTo(streamOutput); } - // TODO Eventually this should be 6.0. But it is 7.0 temporarily for bwc - if (streamOutput.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + if (streamOutput.getVersion().onOrAfter(Version.V_6_1_0)) { if (trialVersion == null) { streamOutput.writeBoolean(false); } else { @@ -177,8 +176,7 @@ class LicensesMetaData extends AbstractNamedDiffable implements } else { license = LICENSE_TOMBSTONE; } - // TODO Eventually this should be 6.0. But it is 7.0 temporarily for bwc - if (streamInput.getVersion().onOrAfter(Version.V_7_0_0_alpha1)) { + if (streamInput.getVersion().onOrAfter(Version.V_6_1_0)) { boolean hasExercisedTrial = streamInput.readBoolean(); if (hasExercisedTrial) { this.trialVersion = Version.readVersion(streamInput); From 7b8d92a2a779c12aff4e8080d3bc80bb5caa9fd5 Mon Sep 17 00:00:00 2001 From: jaymode Date: Mon, 25 Sep 2017 13:02:22 -0600 Subject: [PATCH 3/9] Test: fix AuthenticationService tests timeouts due to incorrect stream sizes The AuthenticationService#testInvalidToken would cause a suite timeout in the case of an exception due to a incorrect stream size as the latch was never counted down. This fixes the missing latch countdown. relates elastic/x-pack-elasticsearch#2615 Original commit: elastic/x-pack-elasticsearch@e838e6e912560d04cabd4a6f3755c20b7c22ca58 --- .../xpack/security/authc/AuthenticationServiceTests.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java index ba6b61d91d7..8a34e61cf5b 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/AuthenticationServiceTests.java @@ -830,6 +830,7 @@ public class AuthenticationServiceTests extends ESTestCase { random().nextBytes(randomBytes); final CountDownLatch latch = new CountDownLatch(1); final Authentication expected = new Authentication(user, new RealmRef(firstRealm.name(), firstRealm.type(), "authc_test"), null); + AtomicBoolean success = new AtomicBoolean(false); try (ThreadContext.StoredContext ignore = threadContext.stashContext()) { threadContext.putHeader("Authorization", "Bearer " + Base64.getEncoder().encodeToString(randomBytes)); service.authenticate("_action", message, null, ActionListener.wrap(result -> { @@ -839,18 +840,22 @@ public class AuthenticationServiceTests extends ESTestCase { assertThat(result.getAuthenticatedBy(), is(notNullValue())); assertThreadContextContainsAuthentication(result); assertEquals(expected, result); + success.set(true); latch.countDown(); }, this::logAndFail)); } catch (IllegalArgumentException ex) { assertThat(ex.getMessage(), containsString("array length must be <= to " + ArrayUtil.MAX_ARRAY_LENGTH + " but was: ")); + latch.countDown(); } catch (NegativeArraySizeException ex) { assertThat(ex.getMessage(), containsString("array size must be positive but was: ")); - + latch.countDown(); } // we need to use a latch here because the key computation goes async on another thread! latch.await(); - verify(auditTrail).authenticationSuccess(firstRealm.name(), user, "_action", message); + if (success.get()) { + verify(auditTrail).authenticationSuccess(firstRealm.name(), user, "_action", message); + } verifyNoMoreInteractions(auditTrail); } From 048418aca71da26bbd5a7b7c6aef82e7d07af11f Mon Sep 17 00:00:00 2001 From: Tal Levy Date: Mon, 25 Sep 2017 22:03:46 -0700 Subject: [PATCH 4/9] add dummy test to LicensingTribeIT for build to pass (elastic/x-pack-elasticsearch#2627) The true purpose of this test is to introduce another test alongside the original, so that the test suite passes even if the other test is skipped due to the assumption it makes about `build.snapshot`. Original commit: elastic/x-pack-elasticsearch@709d7a5dc5deb9d9a82a9e48a50e2aa493da83bb --- .../test/java/org/elasticsearch/test/LicensingTribeIT.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/qa/tribe-tests-with-license/src/test/java/org/elasticsearch/test/LicensingTribeIT.java b/qa/tribe-tests-with-license/src/test/java/org/elasticsearch/test/LicensingTribeIT.java index c2f46379ebb..d36f09fb786 100644 --- a/qa/tribe-tests-with-license/src/test/java/org/elasticsearch/test/LicensingTribeIT.java +++ b/qa/tribe-tests-with-license/src/test/java/org/elasticsearch/test/LicensingTribeIT.java @@ -145,6 +145,11 @@ public class LicensingTribeIT extends ESIntegTestCase { }); } + public void testDummy() throws Exception { + // this test is here so that testLicensePropagateToTribeNode's assumption + // doesn't result in this test suite to have no tests run and trigger a build failure + } + private static final String PLATINUM_LICENSE = "{\"license\":{\"uid\":\"1\",\"type\":\"platinum\"," + "\"issue_date_in_millis\":1411948800000,\"expiry_date_in_millis\":1914278399999,\"max_nodes\":1," + "\"issued_to\":\"issuedTo\",\"issuer\":\"issuer\"," + From a3984f7baa75faa14e55ffc359c3a7743be5cb6d Mon Sep 17 00:00:00 2001 From: Tanguy Leroux Date: Tue, 26 Sep 2017 09:37:59 +0200 Subject: [PATCH 5/9] [Monitoring] Remove MonitoringSettings (elastic/x-pack-elasticsearch#2596) Original commit: elastic/x-pack-elasticsearch@28dea7b6997283cf797a4e2d293188320241b572 --- docs/en/settings/monitoring-settings.asciidoc | 12 +- .../license/XPackLicenseState.java | 4 +- .../org/elasticsearch/xpack/XPackPlugin.java | 5 +- .../xpack/monitoring/Monitoring.java | 60 +++- .../xpack/monitoring/MonitoringService.java | 25 +- .../xpack/monitoring/MonitoringSettings.java | 258 ------------------ .../monitoring/cleaner/CleanerService.java | 19 +- .../xpack/monitoring/collector/Collector.java | 65 ++++- .../cluster/ClusterStatsCollector.java | 15 +- .../indices/IndexRecoveryCollector.java | 29 +- .../indices/IndexStatsCollector.java | 15 +- .../collector/ml/JobStatsCollector.java | 17 +- .../collector/node/NodeStatsCollector.java | 14 +- .../collector/shards/ShardsCollector.java | 16 +- .../xpack/monitoring/exporter/Exporter.java | 5 +- .../xpack/monitoring/exporter/Exporters.java | 13 +- ...nitoringHistoryDurationSettingsTests.java} | 25 +- .../monitoring/MonitoringPluginTests.java | 2 +- .../monitoring/MonitoringServiceTests.java | 18 +- .../MonitoringSettingsIntegTests.java | 167 ------------ .../monitoring/MultiNodesStatsTests.java | 3 +- ...ingIndicesBackwardsCompatibilityTests.java | 11 +- .../AbstractIndicesCleanerTestCase.java | 7 +- .../cleaner/CleanerServiceTests.java | 14 +- .../collector/BaseCollectorTestCase.java | 35 ++- .../cluster/ClusterStatsCollectorTests.java | 14 +- .../indices/IndexRecoveryCollectorTests.java | 36 ++- .../indices/IndexStatsCollectorTests.java | 19 +- .../collector/ml/JobStatsCollectorTests.java | 18 +- .../node/NodeStatsCollectorTests.java | 29 +- .../shards/ShardsCollectorTests.java | 14 +- .../monitoring/exporter/ExportersTests.java | 8 +- .../exporter/http/HttpExporterIT.java | 4 +- .../local/LocalExporterIntegTestCase.java | 4 +- .../local/LocalExporterIntegTests.java | 6 +- .../MonitoringInternalClientTests.java | 4 +- .../MonitoringSettingsFilterTests.java | 4 +- .../test/MonitoringIntegTestCase.java | 3 +- 38 files changed, 386 insertions(+), 631 deletions(-) delete mode 100644 plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringSettings.java rename plugin/src/test/java/org/elasticsearch/xpack/monitoring/{MonitoringSettingsTests.java => MonitoringHistoryDurationSettingsTests.java} (50%) delete mode 100644 plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringSettingsIntegTests.java diff --git a/docs/en/settings/monitoring-settings.asciidoc b/docs/en/settings/monitoring-settings.asciidoc index 0a602c80b80..9458bbaba68 100644 --- a/docs/en/settings/monitoring-settings.asciidoc +++ b/docs/en/settings/monitoring-settings.asciidoc @@ -30,13 +30,9 @@ Set to `false` to disable {es} {monitoring} for Elasticsearch. The `xpack.monitoring.collection` settings control how data is collected from your Elasticsearch nodes. -`xpack.monitoring.collection.cluster.state.timeout`:: - -Sets the timeout for collecting the cluster state. Defaults to `10m`. - `xpack.monitoring.collection.cluster.stats.timeout`:: -Sets the timeout for collecting the cluster statistics. Defaults to `10m`. +Sets the timeout for collecting the cluster statistics. Defaults to `10s`. `xpack.monitoring.collection.indices`:: @@ -50,11 +46,11 @@ You can update this setting through the Cluster Update Settings API. `xpack.monitoring.collection.index.stats.timeout`:: -Sets the timeout for collecting index statistics. Defaults to `10m`. +Sets the timeout for collecting index statistics. Defaults to `10s`. `xpack.monitoring.collection.indices.stats.timeout`:: -Sets the timeout for collecting total indices statistics. Defaults to `10m`. +Sets the timeout for collecting total indices statistics. Defaults to `10s`. `xpack.monitoring.collection.index.recovery.active_only`:: @@ -63,7 +59,7 @@ collect only active recoveries. Defaults to `false`. `xpack.monitoring.collection.index.recovery.timeout`:: -Sets the timeout for collecting the recovery information. Defaults to `10m`. +Sets the timeout for collecting the recovery information. Defaults to `10s`. `xpack.monitoring.collection.interval`:: diff --git a/plugin/src/main/java/org/elasticsearch/license/XPackLicenseState.java b/plugin/src/main/java/org/elasticsearch/license/XPackLicenseState.java index de331f153c2..e5c33c782eb 100644 --- a/plugin/src/main/java/org/elasticsearch/license/XPackLicenseState.java +++ b/plugin/src/main/java/org/elasticsearch/license/XPackLicenseState.java @@ -10,7 +10,7 @@ import org.elasticsearch.common.logging.LoggerMessageFormat; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.License.OperationMode; import org.elasticsearch.xpack.XPackPlugin; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.Monitoring; import java.util.Collections; import java.util.LinkedHashMap; @@ -155,7 +155,7 @@ public class XPackLicenseState { newMode, newMode, newMode), LoggerMessageFormat.format( "Automatic index cleanup is locked to {} days for clusters with [{}] license.", - MonitoringSettings.HISTORY_DURATION.getDefault(Settings.EMPTY).days(), newMode) + Monitoring.HISTORY_DURATION.getDefault(Settings.EMPTY).days(), newMode) }; } break; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java b/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java index 00e33344090..bcf338698ac 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/XPackPlugin.java @@ -81,7 +81,6 @@ import org.elasticsearch.xpack.ml.MachineLearning; import org.elasticsearch.xpack.ml.MachineLearningFeatureSet; import org.elasticsearch.xpack.monitoring.Monitoring; import org.elasticsearch.xpack.monitoring.MonitoringFeatureSet; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.notification.email.Account; import org.elasticsearch.xpack.notification.email.EmailService; import org.elasticsearch.xpack.notification.email.attachment.DataAttachmentParser; @@ -385,7 +384,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I public List> getSettings() { ArrayList> settings = new ArrayList<>(); settings.addAll(Security.getSettings(transportClientMode, extensionsService)); - settings.addAll(MonitoringSettings.getSettings()); + settings.addAll(monitoring.getSettings()); settings.addAll(watcher.getSettings()); settings.addAll(machineLearning.getSettings()); settings.addAll(licensing.getSettings()); @@ -421,7 +420,7 @@ public class XPackPlugin extends Plugin implements ScriptPlugin, ActionPlugin, I filters.add("xpack.notification.pagerduty.account.*." + PagerDutyAccount.SERVICE_KEY_SETTING); filters.add("xpack.notification.hipchat.account.*.auth_token"); filters.addAll(security.getSettingsFilter(extensionsService)); - filters.addAll(MonitoringSettings.getSettingsFilter()); + filters.addAll(monitoring.getSettingsFilter()); if (transportClientMode == false) { for (XPackExtension extension : extensionsService.getExtensions()) { filters.addAll(extension.getSettingsFilter()); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/Monitoring.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/Monitoring.java index 4ba172ab524..f11a7031f10 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/Monitoring.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/Monitoring.java @@ -14,8 +14,10 @@ import org.elasticsearch.common.inject.Module; import org.elasticsearch.common.inject.util.Providers; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.IndexScopedSettings; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.SettingsFilter; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.LicenseService; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.plugins.ActionPlugin; @@ -55,6 +57,7 @@ import java.util.function.Supplier; import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; +import static org.elasticsearch.common.settings.Setting.timeSetting; /** * This class activates/deactivates the monitoring modules depending if we're running a node client, transport client or tribe client: @@ -66,6 +69,27 @@ public class Monitoring implements ActionPlugin { public static final String NAME = "monitoring"; + /** + * The minimum amount of time allowed for the history duration. + */ + public static final TimeValue HISTORY_DURATION_MINIMUM = TimeValue.timeValueHours(24); + + /** + * The default retention duration of the monitoring history data. + *

+ * Expected values: + *

    + *
  • Default: 7 days
  • + *
  • Minimum: 1 day
  • + *
+ * + * @see #HISTORY_DURATION_MINIMUM + */ + public static final Setting HISTORY_DURATION = timeSetting("xpack.monitoring.history.duration", + TimeValue.timeValueHours(7 * 24), // default value (7 days) + HISTORY_DURATION_MINIMUM, // minimum value + Setting.Property.Dynamic, Setting.Property.NodeScope); + private final Settings settings; private final XPackLicenseState licenseState; private final boolean enabled; @@ -106,7 +130,6 @@ public class Monitoring implements ActionPlugin { } final ClusterSettings clusterSettings = clusterService.getClusterSettings(); - final MonitoringSettings monitoringSettings = new MonitoringSettings(settings, clusterSettings); final CleanerService cleanerService = new CleanerService(settings, clusterSettings, threadPool, licenseState); final SSLService dynamicSSLService = sslService.createDynamicSSLService(); @@ -116,16 +139,16 @@ public class Monitoring implements ActionPlugin { final Exporters exporters = new Exporters(settings, exporterFactories, clusterService, licenseState, threadPool.getThreadContext()); Set collectors = new HashSet<>(); - collectors.add(new IndexStatsCollector(settings, clusterService, monitoringSettings, licenseState, client)); - collectors.add(new ClusterStatsCollector(settings, clusterService, monitoringSettings, licenseState, client, licenseService)); - collectors.add(new ShardsCollector(settings, clusterService, monitoringSettings, licenseState)); - collectors.add(new NodeStatsCollector(settings, clusterService, monitoringSettings, licenseState, client)); - collectors.add(new IndexRecoveryCollector(settings, clusterService, monitoringSettings, licenseState, client)); - collectors.add(new JobStatsCollector(settings, clusterService, monitoringSettings, licenseState, client)); + collectors.add(new IndexStatsCollector(settings, clusterService, licenseState, client)); + collectors.add(new ClusterStatsCollector(settings, clusterService, licenseState, client, licenseService)); + collectors.add(new ShardsCollector(settings, clusterService, licenseState)); + collectors.add(new NodeStatsCollector(settings, clusterService, licenseState, client)); + collectors.add(new IndexRecoveryCollector(settings, clusterService, licenseState, client)); + collectors.add(new JobStatsCollector(settings, clusterService, licenseState, client)); final MonitoringService monitoringService = new MonitoringService(settings, clusterSettings, threadPool, collectors, exporters); - return Arrays.asList(monitoringService, monitoringSettings, exporters, cleanerService); + return Arrays.asList(monitoringService, exporters, cleanerService); } @Override @@ -145,4 +168,25 @@ public class Monitoring implements ActionPlugin { } return singletonList(new RestMonitoringBulkAction(settings, restController)); } + + public List> getSettings() { + return Collections.unmodifiableList( + Arrays.asList(HISTORY_DURATION, + MonitoringService.INTERVAL, + Exporters.EXPORTERS_SETTINGS, + Collector.INDICES, + ClusterStatsCollector.CLUSTER_STATS_TIMEOUT, + IndexRecoveryCollector.INDEX_RECOVERY_TIMEOUT, + IndexRecoveryCollector.INDEX_RECOVERY_ACTIVE_ONLY, + IndexStatsCollector.INDEX_STATS_TIMEOUT, + JobStatsCollector.JOB_STATS_TIMEOUT, + NodeStatsCollector.NODE_STATS_TIMEOUT) + ); + } + + public List getSettingsFilter() { + final String exportersKey = Exporters.EXPORTERS_SETTINGS.getKey(); + return Collections.unmodifiableList(Arrays.asList(exportersKey + "*.auth.*", exportersKey + "*.ssl.*")); + } + } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringService.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringService.java index 2200fee305c..ad0a24e62fc 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringService.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringService.java @@ -10,6 +10,7 @@ import org.apache.logging.log4j.util.Supplier; import org.elasticsearch.action.ActionListener; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.settings.ClusterSettings; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.util.concurrent.AbstractRunnable; @@ -36,6 +37,24 @@ import java.util.concurrent.atomic.AtomicBoolean; */ public class MonitoringService extends AbstractLifecycleComponent { + /** + * Minimum value for sampling interval (1 second) + */ + static final TimeValue MIN_INTERVAL = TimeValue.timeValueSeconds(1L); + + /** + * Sampling interval between two collections (default to 10s) + */ + public static final Setting INTERVAL = new Setting<>("xpack.monitoring.collection.interval", "10s", + (s) -> { + TimeValue value = TimeValue.parseTimeValue(s, null, "xpack.monitoring.collection.interval"); + if (TimeValue.MINUS_ONE.equals(value) || value.millis() >= MIN_INTERVAL.millis()) { + return value; + } + throw new IllegalArgumentException("Failed to parse monitoring interval [" + s + "], value must be >= " + MIN_INTERVAL); + }, + Setting.Property.Dynamic, Setting.Property.NodeScope); + /** State of the monitoring service, either started or stopped **/ private final AtomicBoolean started = new AtomicBoolean(false); @@ -55,8 +74,8 @@ public class MonitoringService extends AbstractLifecycleComponent { this.threadPool = Objects.requireNonNull(threadPool); this.collectors = Objects.requireNonNull(collectors); this.exporters = Objects.requireNonNull(exporters); - this.interval = MonitoringSettings.INTERVAL.get(settings); - clusterSettings.addSettingsUpdateConsumer(MonitoringSettings.INTERVAL, this::setInterval); + this.interval = INTERVAL.get(settings); + clusterSettings.addSettingsUpdateConsumer(INTERVAL, this::setInterval); } void setInterval(TimeValue interval) { @@ -71,7 +90,7 @@ public class MonitoringService extends AbstractLifecycleComponent { boolean isMonitoringActive() { return isStarted() && interval != null - && interval.millis() >= MonitoringSettings.MIN_INTERVAL.millis(); + && interval.millis() >= MIN_INTERVAL.millis(); } private String threadPoolName() { diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringSettings.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringSettings.java deleted file mode 100644 index 8ced786435a..00000000000 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringSettings.java +++ /dev/null @@ -1,258 +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.monitoring; - -import org.elasticsearch.common.component.AbstractComponent; -import org.elasticsearch.common.settings.ClusterSettings; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.xpack.XPackPlugin; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.function.Function; - -import static org.elasticsearch.common.settings.Setting.Property; -import static org.elasticsearch.common.settings.Setting.boolSetting; -import static org.elasticsearch.common.settings.Setting.groupSetting; -import static org.elasticsearch.common.settings.Setting.listSetting; -import static org.elasticsearch.common.settings.Setting.timeSetting; - -// TODO Remove this class and put the settings in Monitoring class -public class MonitoringSettings extends AbstractComponent { - - public static final String HISTORY_DURATION_SETTING_NAME = "history.duration"; - /** - * The minimum amount of time allowed for the history duration. - */ - public static final TimeValue HISTORY_DURATION_MINIMUM = TimeValue.timeValueHours(24); - - /** - * Minimum value for sampling interval (1 second) - */ - static final TimeValue MIN_INTERVAL = TimeValue.timeValueSeconds(1L); - - /** - * Sampling interval between two collections (default to 10s) - */ - public static final Setting INTERVAL = new Setting<>(collectionKey("interval"), "10s", - (s) -> { - TimeValue value = TimeValue.parseTimeValue(s, null, collectionKey("interval")); - if (TimeValue.MINUS_ONE.equals(value) || value.millis() >= MIN_INTERVAL.millis()) { - return value; - } - throw new IllegalArgumentException("Failed to parse monitoring interval [" + s + "], value must be >= " + MIN_INTERVAL); - }, - Property.Dynamic, Property.NodeScope); - - /** - * Timeout value when collecting index statistics (default to 10s) - */ - public static final Setting INDEX_STATS_TIMEOUT = - timeSetting(collectionKey("index.stats.timeout"), TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); - - /** - * List of indices names whose stats will be exported (default to all indices) - */ - public static final Setting> INDICES = - listSetting(collectionKey("indices"), Collections.emptyList(), Function.identity(), Property.Dynamic, Property.NodeScope); - - /** - * Timeout value when collecting the cluster state (default to 10s) - */ - public static final Setting CLUSTER_STATE_TIMEOUT = - timeSetting(collectionKey("cluster.state.timeout"), TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); - - /** - * Timeout value when collecting the recovery information (default to 10s) - */ - public static final Setting CLUSTER_STATS_TIMEOUT = - timeSetting(collectionKey("cluster.stats.timeout"), TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); - - /** - * Timeout value when collecting ML job statistics (default to 10s) - */ - public static final Setting JOB_STATS_TIMEOUT = - timeSetting(collectionKey("ml.job.stats.timeout"), TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); - - /** - * Timeout value when collecting the nodes statistics (default to 10s) - */ - public static final Setting NODE_STATS_TIMEOUT = - timeSetting(collectionKey("node.stats.timeout"), TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); - - /** - * Timeout value when collecting the recovery information (default to 10s) - */ - public static final Setting INDEX_RECOVERY_TIMEOUT = - timeSetting(collectionKey("index.recovery.timeout"), TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); - - /** - * Flag to indicate if only active recoveries should be collected (default to false: all recoveries are collected) - */ - public static final Setting INDEX_RECOVERY_ACTIVE_ONLY = - boolSetting(collectionKey("index.recovery.active_only"), false, Property.Dynamic, Property.NodeScope) ; - - /** - * The default retention duration of the monitoring history data. - *

- * Expected values: - *

    - *
  • Default: 7 days
  • - *
  • Minimum: 1 day
  • - *
- * - * @see #HISTORY_DURATION_MINIMUM - */ - public static final Setting HISTORY_DURATION = - timeSetting(key(HISTORY_DURATION_SETTING_NAME), - TimeValue.timeValueHours(7 * 24), // default value (7 days) - HISTORY_DURATION_MINIMUM, // minimum value - Property.Dynamic, Property.NodeScope); - - /** - * Settings/Options per configured exporter - */ - public static final Setting EXPORTERS_SETTINGS = - groupSetting(key("exporters."), Property.Dynamic, Property.NodeScope); - - public static List> getSettings() { - return Arrays.asList(INDICES, - INTERVAL, - INDEX_RECOVERY_TIMEOUT, - INDEX_STATS_TIMEOUT, - INDEX_RECOVERY_ACTIVE_ONLY, - CLUSTER_STATE_TIMEOUT, - CLUSTER_STATS_TIMEOUT, - JOB_STATS_TIMEOUT, - NODE_STATS_TIMEOUT, - HISTORY_DURATION, - EXPORTERS_SETTINGS); - } - - public static List getSettingsFilter() { - return Arrays.asList(key("exporters.*.auth.*"), key("exporters.*.ssl.*")); - } - - - private volatile TimeValue indexStatsTimeout; - private volatile TimeValue clusterStateTimeout; - private volatile TimeValue clusterStatsTimeout; - private volatile TimeValue recoveryTimeout; - private volatile TimeValue jobStatsTimeout; - private volatile TimeValue nodeStatsTimeout; - private volatile boolean recoveryActiveOnly; - private volatile String[] indices; - - public MonitoringSettings(Settings settings, ClusterSettings clusterSettings) { - super(settings); - - setIndexStatsTimeout(INDEX_STATS_TIMEOUT.get(settings)); - clusterSettings.addSettingsUpdateConsumer(INDEX_STATS_TIMEOUT, this::setIndexStatsTimeout); - setIndices(INDICES.get(settings)); - clusterSettings.addSettingsUpdateConsumer(INDICES, this::setIndices); - setClusterStateTimeout(CLUSTER_STATE_TIMEOUT.get(settings)); - clusterSettings.addSettingsUpdateConsumer(CLUSTER_STATE_TIMEOUT, this::setClusterStateTimeout); - setClusterStatsTimeout(CLUSTER_STATS_TIMEOUT.get(settings)); - clusterSettings.addSettingsUpdateConsumer(CLUSTER_STATS_TIMEOUT, this::setClusterStatsTimeout); - setJobStatsTimeout(JOB_STATS_TIMEOUT.get(settings)); - clusterSettings.addSettingsUpdateConsumer(JOB_STATS_TIMEOUT, this::setJobStatsTimeout); - setNodeStatsTimeout(NODE_STATS_TIMEOUT.get(settings)); - clusterSettings.addSettingsUpdateConsumer(NODE_STATS_TIMEOUT, this::setNodeStatsTimeout); - setRecoveryTimeout(INDEX_RECOVERY_TIMEOUT.get(settings)); - clusterSettings.addSettingsUpdateConsumer(INDEX_RECOVERY_TIMEOUT, this::setRecoveryTimeout); - setRecoveryActiveOnly(INDEX_RECOVERY_ACTIVE_ONLY.get(settings)); - clusterSettings.addSettingsUpdateConsumer(INDEX_RECOVERY_ACTIVE_ONLY, this::setRecoveryActiveOnly); - } - - public TimeValue indexStatsTimeout() { - return indexStatsTimeout; - } - - public String[] indices() { - return indices; - } - - public TimeValue clusterStateTimeout() { - return clusterStateTimeout; - } - - public TimeValue clusterStatsTimeout() { - return clusterStatsTimeout; - } - - public TimeValue jobStatsTimeout() { - return jobStatsTimeout; - } - - public TimeValue nodeStatsTimeout() { - return nodeStatsTimeout; - } - - public TimeValue recoveryTimeout() { - return recoveryTimeout; - } - - public boolean recoveryActiveOnly() { - return recoveryActiveOnly; - } - - private void setIndexStatsTimeout(TimeValue indexStatsTimeout) { - this.indexStatsTimeout = indexStatsTimeout; - } - - private void setClusterStateTimeout(TimeValue clusterStateTimeout) { - this.clusterStateTimeout = clusterStateTimeout; - } - - private void setClusterStatsTimeout(TimeValue clusterStatsTimeout) { - this.clusterStatsTimeout = clusterStatsTimeout; - } - - private void setJobStatsTimeout(TimeValue jobStatsTimeout) { - this.jobStatsTimeout = jobStatsTimeout; - } - - public void setNodeStatsTimeout(TimeValue nodeStatsTimeout) { - this.nodeStatsTimeout = nodeStatsTimeout; - } - - private void setRecoveryTimeout(TimeValue recoveryTimeout) { - this.recoveryTimeout = recoveryTimeout; - } - - private void setRecoveryActiveOnly(boolean recoveryActiveOnly) { - this.recoveryActiveOnly = recoveryActiveOnly; - } - - private void setIndices(List indices) { - this.indices = indices.toArray(new String[0]); - } - - /** - * Prefix the {@code key} with the Monitoring prefix and "collection." . - * - * @param key The key to prefix - * @return The key prefixed by the product prefixes + "collection." . - * @see #key(String) - */ - static String collectionKey(String key) { - return key("collection." + key); - } - - /** - * Prefix the {@code key} with the Monitoring prefix. - * - * @param key The key to prefix - * @return The key prefixed by the product prefixes. - */ - static String key(String key) { - return XPackPlugin.featureSettingPrefix(Monitoring.NAME) + "." + key; - } - -} diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerService.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerService.java index 790c13c444b..871a5b68a08 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerService.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerService.java @@ -5,10 +5,6 @@ */ package org.elasticsearch.xpack.monitoring.cleaner; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.ScheduledFuture; - import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.settings.ClusterSettings; import org.elasticsearch.common.settings.Settings; @@ -18,10 +14,14 @@ import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; import org.elasticsearch.common.util.concurrent.FutureUtils; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.Monitoring; import org.joda.time.DateTime; import org.joda.time.chrono.ISOChronology; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.ScheduledFuture; + /** * {@code CleanerService} takes care of deleting old monitoring indices. */ @@ -41,11 +41,11 @@ public class CleanerService extends AbstractLifecycleComponent { this.licenseState = licenseState; this.threadPool = threadPool; this.executionScheduler = executionScheduler; - this.globalRetention = MonitoringSettings.HISTORY_DURATION.get(settings); + this.globalRetention = Monitoring.HISTORY_DURATION.get(settings); this.runnable = new IndicesCleaner(); // the validation is performed by the setting's object itself - clusterSettings.addSettingsUpdateConsumer(MonitoringSettings.HISTORY_DURATION, this::setGlobalRetention); + clusterSettings.addSettingsUpdateConsumer(Monitoring.HISTORY_DURATION, this::setGlobalRetention); } public CleanerService(Settings settings, ClusterSettings clusterSettings, ThreadPool threadPool, XPackLicenseState licenseState) { @@ -91,7 +91,7 @@ public class CleanerService extends AbstractLifecycleComponent { return globalRetention; } else { - return MonitoringSettings.HISTORY_DURATION.getDefault(Settings.EMPTY); + return Monitoring.HISTORY_DURATION.getDefault(Settings.EMPTY); } } @@ -106,8 +106,7 @@ public class CleanerService extends AbstractLifecycleComponent { public void setGlobalRetention(TimeValue globalRetention) { // notify the user that their setting will be ignored until they get the right license if (licenseState.isUpdateRetentionAllowed() == false) { - logger.warn("[{}] setting will be ignored until an appropriate license is applied", - MonitoringSettings.HISTORY_DURATION.getKey()); + logger.warn("[{}] setting will be ignored until an appropriate license is applied", Monitoring.HISTORY_DURATION.getKey()); } this.globalRetention = globalRetention; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/Collector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/Collector.java index 4bd5779f610..d7073619ccf 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/Collector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/Collector.java @@ -10,32 +10,50 @@ import org.apache.logging.log4j.util.Supplier; import org.elasticsearch.ElasticsearchTimeoutException; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.component.AbstractComponent; import org.elasticsearch.common.inject.internal.Nullable; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.XPackPlugin; +import org.elasticsearch.xpack.monitoring.Monitoring; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.function.Function; + +import static java.util.Collections.emptyList; +import static org.elasticsearch.common.settings.Setting.Property; +import static org.elasticsearch.common.settings.Setting.listSetting; +import static org.elasticsearch.common.settings.Setting.timeSetting; /** * {@link Collector} are used to collect monitoring data about the cluster, nodes and indices. */ public abstract class Collector extends AbstractComponent { + /** + * List of indices names whose stats will be exported (default to all indices) + */ + public static final Setting> INDICES = + listSetting(collectionSetting("indices"), emptyList(), Function.identity(), Property.Dynamic, Property.NodeScope); + private final String name; + private final Setting collectionTimeoutSetting; protected final ClusterService clusterService; - protected final MonitoringSettings monitoringSettings; protected final XPackLicenseState licenseState; - public Collector(Settings settings, String name, ClusterService clusterService, - MonitoringSettings monitoringSettings, XPackLicenseState licenseState) { + public Collector(final Settings settings, final String name, final ClusterService clusterService, + final Setting timeoutSetting, final XPackLicenseState licenseState) { super(settings); this.name = name; this.clusterService = clusterService; - this.monitoringSettings = monitoringSettings; + this.collectionTimeoutSetting = timeoutSetting; this.licenseState = licenseState; } @@ -92,6 +110,33 @@ public abstract class Collector extends AbstractComponent { return System.currentTimeMillis(); } + /** + * Returns the value of the collection timeout configured for the current {@link Collector}. + * + * @return the collection timeout, or {@code null} if the collector has not timeout defined. + */ + public TimeValue getCollectionTimeout() { + if (collectionTimeoutSetting == null) { + return null; + } + return clusterService.getClusterSettings().get(collectionTimeoutSetting); + } + + /** + * Returns the names of indices Monitoring collects data from. + * + * @return a array of indices + */ + public String[] getCollectionIndices() { + final List indices = clusterService.getClusterSettings().get(INDICES); + assert indices != null; + if (indices.isEmpty()) { + return Strings.EMPTY_ARRAY; + } else { + return indices.toArray(new String[indices.size()]); + } + } + /** * Creates a {@link MonitoringDoc.Node} from a {@link DiscoveryNode} and a timestamp, copying over the * required information. @@ -112,4 +157,14 @@ public abstract class Collector extends AbstractComponent { node.getName(), timestamp); } + + protected static String collectionSetting(final String settingName) { + Objects.requireNonNull(settingName, "setting name must not be null"); + return XPackPlugin.featureSettingPrefix(Monitoring.NAME) + ".collection." + settingName; + } + + protected static Setting collectionTimeoutSetting(final String settingName) { + String name = collectionSetting(settingName); + return timeSetting(name, TimeValue.timeValueSeconds(10), Property.Dynamic, Property.NodeScope); + } } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollector.java index 674209f0b5d..ef7f9d33ca1 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollector.java @@ -14,17 +14,17 @@ import org.elasticsearch.client.Client; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.License; import org.elasticsearch.license.LicenseService; import org.elasticsearch.license.LicenseUtils; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.xpack.XPackFeatureSet; import org.elasticsearch.xpack.action.XPackUsageRequestBuilder; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.Collector; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; -import org.elasticsearch.xpack.security.InternalClient; import java.util.Collection; import java.util.Collections; @@ -42,16 +42,20 @@ import java.util.List; */ public class ClusterStatsCollector extends Collector { + /** + * Timeout value when collecting the cluster stats information (default to 10s) + */ + public static final Setting CLUSTER_STATS_TIMEOUT = collectionTimeoutSetting("cluster.stats.timeout"); + private final LicenseService licenseService; private final Client client; public ClusterStatsCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState, final Client client, final LicenseService licenseService) { - super(settings, ClusterStatsMonitoringDoc.TYPE, clusterService, monitoringSettings, licenseState); + super(settings, ClusterStatsMonitoringDoc.TYPE, clusterService, CLUSTER_STATS_TIMEOUT, licenseState); this.client = client; this.licenseService = licenseService; } @@ -65,8 +69,7 @@ public class ClusterStatsCollector extends Collector { @Override protected Collection doCollect(final MonitoringDoc.Node node) throws Exception { final Supplier clusterStatsSupplier = - () -> client.admin().cluster().prepareClusterStats() - .get(monitoringSettings.clusterStatsTimeout()); + () -> client.admin().cluster().prepareClusterStats().get(getCollectionTimeout()); final Supplier> usageSupplier = () -> new XPackUsageRequestBuilder(client).get().getUsages(); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollector.java index ea88eea3143..a258fb3de0a 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollector.java @@ -9,9 +9,10 @@ import org.elasticsearch.action.admin.indices.recovery.RecoveryResponse; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.Collector; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; @@ -21,6 +22,8 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import static org.elasticsearch.common.settings.Setting.boolSetting; + /** * Collector for the Recovery API. *

@@ -29,18 +32,32 @@ import java.util.Objects; */ public class IndexRecoveryCollector extends Collector { + /** + * Timeout value when collecting the recovery information (default to 10s) + */ + public static final Setting INDEX_RECOVERY_TIMEOUT = collectionTimeoutSetting("index.recovery.timeout"); + + /** + * Flag to indicate if only active recoveries should be collected (default to false: all recoveries are collected) + */ + public static final Setting INDEX_RECOVERY_ACTIVE_ONLY = + boolSetting(collectionSetting("index.recovery.active_only"), false, Setting.Property.Dynamic, Setting.Property.NodeScope); + private final Client client; public IndexRecoveryCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState, final Client client) { - super(settings, IndexRecoveryMonitoringDoc.TYPE, clusterService, monitoringSettings, licenseState); + super(settings, IndexRecoveryMonitoringDoc.TYPE, clusterService, INDEX_RECOVERY_TIMEOUT, licenseState); this.client = Objects.requireNonNull(client); } + boolean getActiveRecoveriesOnly() { + return clusterService.getClusterSettings().get(INDEX_RECOVERY_ACTIVE_ONLY); + } + @Override protected boolean shouldCollect() { return super.shouldCollect() && isLocalNodeMaster(); @@ -50,10 +67,10 @@ public class IndexRecoveryCollector extends Collector { protected Collection doCollect(final MonitoringDoc.Node node) throws Exception { List results = new ArrayList<>(1); RecoveryResponse recoveryResponse = client.admin().indices().prepareRecoveries() - .setIndices(monitoringSettings.indices()) + .setIndices(getCollectionIndices()) .setIndicesOptions(IndicesOptions.lenientExpandOpen()) - .setActiveOnly(monitoringSettings.recoveryActiveOnly()) - .get(monitoringSettings.recoveryTimeout()); + .setActiveOnly(getActiveRecoveriesOnly()) + .get(getCollectionTimeout()); if (recoveryResponse.hasRecoveries()) { results.add(new IndexRecoveryMonitoringDoc(clusterUUID(), timestamp(), node, recoveryResponse)); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollector.java index e8969247f84..175c885aead 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollector.java @@ -10,9 +10,10 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsResponse; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.Collector; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; @@ -29,14 +30,18 @@ import java.util.List; */ public class IndexStatsCollector extends Collector { + /** + * Timeout value when collecting index statistics (default to 10s) + */ + public static final Setting INDEX_STATS_TIMEOUT = collectionTimeoutSetting("index.stats.timeout"); + private final Client client; public IndexStatsCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState, final Client client) { - super(settings, "index-stats", clusterService, monitoringSettings, licenseState); + super(settings, "index-stats", clusterService, INDEX_STATS_TIMEOUT, licenseState); this.client = client; } @@ -49,7 +54,7 @@ public class IndexStatsCollector extends Collector { protected Collection doCollect(final MonitoringDoc.Node node) throws Exception { final List results = new ArrayList<>(); final IndicesStatsResponse indicesStats = client.admin().indices().prepareStats() - .setIndices(monitoringSettings.indices()) + .setIndices(getCollectionIndices()) .setIndicesOptions(IndicesOptions.lenientExpandOpen()) .clear() .setDocs(true) @@ -62,7 +67,7 @@ public class IndexStatsCollector extends Collector { .setRefresh(true) .setQueryCache(true) .setRequestCache(true) - .get(monitoringSettings.indexStatsTimeout()); + .get(getCollectionTimeout()); final long timestamp = timestamp(); final String clusterUuid = clusterUUID(); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollector.java index 35ac3c073de..d564a7f0d59 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollector.java @@ -6,15 +6,15 @@ package org.elasticsearch.xpack.monitoring.collector.ml; import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.xpack.XPackClient; import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.ml.action.GetJobsStatsAction; import org.elasticsearch.xpack.ml.client.MachineLearningClient; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.Collector; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; import org.elasticsearch.xpack.security.InternalClient; @@ -32,18 +32,21 @@ import java.util.stream.Collectors; */ public class JobStatsCollector extends Collector { + /** + * Timeout value when collecting ML job statistics (default to 10s) + */ + public static final Setting JOB_STATS_TIMEOUT = collectionTimeoutSetting("ml.job.stats.timeout"); + private final MachineLearningClient client; public JobStatsCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState, final InternalClient client) { - this(settings, clusterService, monitoringSettings, licenseState, new XPackClient(client).machineLearning()); + this(settings, clusterService, licenseState, new XPackClient(client).machineLearning()); } JobStatsCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState, final MachineLearningClient client) { - super(settings, JobStatsMonitoringDoc.TYPE, clusterService, monitoringSettings, licenseState); + super(settings, JobStatsMonitoringDoc.TYPE, clusterService, JOB_STATS_TIMEOUT, licenseState); this.client = client; } @@ -61,7 +64,7 @@ public class JobStatsCollector extends Collector { // fetch details about all jobs final GetJobsStatsAction.Response jobs = client.getJobsStats(new GetJobsStatsAction.Request(MetaData.ALL)) - .actionGet(monitoringSettings.jobStatsTimeout()); + .actionGet(getCollectionTimeout()); final long timestamp = timestamp(); final String clusterUuid = clusterUUID(); diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollector.java index 9c19931906b..5901c937057 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollector.java @@ -12,9 +12,10 @@ import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags; import org.elasticsearch.bootstrap.BootstrapInfo; import org.elasticsearch.client.Client; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.Collector; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; @@ -30,6 +31,11 @@ import java.util.Objects; */ public class NodeStatsCollector extends Collector { + /** + * Timeout value when collecting the nodes statistics (default to 10s) + */ + public static final Setting NODE_STATS_TIMEOUT = collectionTimeoutSetting("node.stats.timeout"); + private static final CommonStatsFlags FLAGS = new CommonStatsFlags(CommonStatsFlags.Flag.Docs, CommonStatsFlags.Flag.FieldData, @@ -44,10 +50,10 @@ public class NodeStatsCollector extends Collector { public NodeStatsCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState, final Client client) { - super(settings, NodeStatsMonitoringDoc.TYPE, clusterService, monitoringSettings, licenseState); + + super(settings, NodeStatsMonitoringDoc.TYPE, clusterService, NODE_STATS_TIMEOUT, licenseState); this.client = Objects.requireNonNull(client); } @@ -67,7 +73,7 @@ public class NodeStatsCollector extends Collector { request.threadPool(true); request.fs(true); - final NodesStatsResponse response = client.admin().cluster().nodesStats(request).actionGet(monitoringSettings.nodeStatsTimeout()); + final NodesStatsResponse response = client.admin().cluster().nodesStats(request).actionGet(getCollectionTimeout()); // if there's a failure, then we failed to work with the // _local node (guaranteed a single exception) diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollector.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollector.java index c80380a3df9..f8d7244814c 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollector.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollector.java @@ -13,7 +13,6 @@ import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.Collector; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; @@ -33,10 +32,9 @@ public class ShardsCollector extends Collector { public ShardsCollector(final Settings settings, final ClusterService clusterService, - final MonitoringSettings monitoringSettings, final XPackLicenseState licenseState) { - super(settings, ShardMonitoringDoc.TYPE, clusterService, monitoringSettings, licenseState); + super(settings, ShardMonitoringDoc.TYPE, clusterService, null, licenseState); } @Override @@ -48,7 +46,7 @@ public class ShardsCollector extends Collector { protected Collection doCollect(final MonitoringDoc.Node node) throws Exception { final List results = new ArrayList<>(1); - ClusterState clusterState = clusterService.state(); + final ClusterState clusterState = clusterService.state(); if (clusterState != null) { RoutingTable routingTable = clusterState.routingTable(); if (routingTable != null) { @@ -58,8 +56,11 @@ public class ShardsCollector extends Collector { final String stateUUID = clusterState.stateUUID(); final long timestamp = timestamp(); + final String[] indices = getCollectionIndices(); + final boolean isAllIndices = IndexNameExpressionResolver.isAllIndices(Arrays.asList(indices)); + for (ShardRouting shard : shards) { - if (match(shard.getIndexName())) { + if (isAllIndices || Regex.simpleMatch(indices, shard.getIndexName())) { MonitoringDoc.Node shardNode = null; if (shard.assignedToNode()) { // If the shard is assigned to a node, the shard monitoring document refers to this node @@ -73,9 +74,4 @@ public class ShardsCollector extends Collector { } return Collections.unmodifiableCollection(results); } - - private boolean match(final String indexName) { - final String[] indices = monitoringSettings.indices(); - return IndexNameExpressionResolver.isAllIndices(Arrays.asList(indices)) || Regex.simpleMatch(indices, indexName); - } } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporter.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporter.java index e469d71970e..59f3c27db14 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporter.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporter.java @@ -9,7 +9,6 @@ import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.joda.time.format.DateTimeFormat; import org.joda.time.format.DateTimeFormatter; @@ -73,11 +72,11 @@ public abstract class Exporter implements AutoCloseable { protected abstract void doClose(); protected static String settingFQN(final Config config) { - return MonitoringSettings.EXPORTERS_SETTINGS.getKey() + config.name; + return Exporters.EXPORTERS_SETTINGS.getKey() + config.name; } protected static String settingFQN(final Config config, final String setting) { - return MonitoringSettings.EXPORTERS_SETTINGS.getKey() + config.name + "." + setting; + return Exporters.EXPORTERS_SETTINGS.getKey() + config.name + "." + setting; } protected static DateTimeFormatter dateTimeFormatter(final Config config) { diff --git a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java index f66f7bbc8c1..04478e01f9b 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/monitoring/exporter/Exporters.java @@ -13,11 +13,11 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.component.AbstractLifecycleComponent; import org.elasticsearch.common.component.Lifecycle; +import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.SettingsException; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.license.XPackLicenseState; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.exporter.local.LocalExporter; import java.util.ArrayList; @@ -32,9 +32,16 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import static java.util.Collections.emptyMap; +import static org.elasticsearch.common.settings.Setting.groupSetting; public class Exporters extends AbstractLifecycleComponent implements Iterable { + /** + * Settings/Options per configured exporter + */ + public static final Setting EXPORTERS_SETTINGS = + groupSetting("xpack.monitoring.exporters.", Setting.Property.Dynamic, Setting.Property.NodeScope); + private final Map factories; private final AtomicReference> exporters; private final ClusterService clusterService; @@ -52,7 +59,7 @@ public class Exporters extends AbstractLifecycleComponent implements Iterable Monitoring.HISTORY_DURATION.get(buildSettings(Monitoring.HISTORY_DURATION.getKey(), oneSecondEarly))); } private Settings buildSettings(String key, String value) { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringPluginTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringPluginTests.java index 1e697884b07..21834f5add4 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringPluginTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringPluginTests.java @@ -86,7 +86,7 @@ public class MonitoringPluginTests extends MonitoringIntegTestCase { protected Settings nodeSettings(int nodeOrdinal) { return Settings.builder() .put(super.nodeSettings(nodeOrdinal)) - .put(MonitoringSettings.INTERVAL.getKey(), "-1") + .put(MonitoringService.INTERVAL.getKey(), "-1") .build(); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringServiceTests.java index 54665675c4d..25d33890e12 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringServiceTests.java @@ -33,18 +33,20 @@ import static org.mockito.Mockito.when; public class MonitoringServiceTests extends ESTestCase { - TestThreadPool threadPool; - MonitoringService monitoringService; - XPackLicenseState licenseState = mock(XPackLicenseState.class); - ClusterService clusterService; - ClusterSettings clusterSettings; + private TestThreadPool threadPool; + private MonitoringService monitoringService; + private XPackLicenseState licenseState = mock(XPackLicenseState.class); + private ClusterService clusterService; + private ClusterSettings clusterSettings; @Before public void setUp() throws Exception { super.setUp(); threadPool = new TestThreadPool(getTestName()); clusterService = mock(ClusterService.class); - clusterSettings = new ClusterSettings(Settings.EMPTY, new HashSet<>(MonitoringSettings.getSettings())); + + final Monitoring monitoring = new Monitoring(Settings.EMPTY, licenseState); + clusterSettings = new ClusterSettings(Settings.EMPTY, new HashSet<>(monitoring.getSettings())); when(clusterService.getClusterSettings()).thenReturn(clusterSettings); } @@ -77,7 +79,7 @@ public class MonitoringServiceTests extends ESTestCase { } public void testInterval() throws Exception { - Settings settings = Settings.builder().put(MonitoringSettings.INTERVAL.getKey(), TimeValue.MINUS_ONE).build(); + Settings settings = Settings.builder().put(MonitoringService.INTERVAL.getKey(), TimeValue.MINUS_ONE).build(); CountingExporter exporter = new CountingExporter(); monitoringService = new MonitoringService(settings, clusterSettings, threadPool, emptySet(), exporter); @@ -102,7 +104,7 @@ public class MonitoringServiceTests extends ESTestCase { final CountDownLatch latch = new CountDownLatch(1); final BlockingExporter exporter = new BlockingExporter(latch); - Settings settings = Settings.builder().put(MonitoringSettings.INTERVAL.getKey(), MonitoringSettings.MIN_INTERVAL).build(); + Settings settings = Settings.builder().put(MonitoringService.INTERVAL.getKey(), MonitoringService.MIN_INTERVAL).build(); monitoringService = new MonitoringService(settings, clusterSettings, threadPool, emptySet(), exporter); monitoringService.start(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringSettingsIntegTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringSettingsIntegTests.java deleted file mode 100644 index 7a05a291e06..00000000000 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MonitoringSettingsIntegTests.java +++ /dev/null @@ -1,167 +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.monitoring; - -import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequestBuilder; -import org.elasticsearch.common.network.NetworkModule; -import org.elasticsearch.common.settings.Setting; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.plugins.Plugin; -import org.elasticsearch.test.ESIntegTestCase; -import org.elasticsearch.transport.Netty4Plugin; -import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; -import static org.hamcrest.Matchers.equalTo; - -@ESIntegTestCase.ClusterScope(scope = ESIntegTestCase.Scope.TEST, supportsDedicatedMasters = false, numDataNodes = 1, numClientNodes = 0) -public class MonitoringSettingsIntegTests extends MonitoringIntegTestCase { - private final TimeValue interval = newRandomTimeValue(); - private final TimeValue indexStatsTimeout = newRandomTimeValue(); - private final String[] indices = randomStringArray(); - private final TimeValue clusterStateTimeout = newRandomTimeValue(); - private final TimeValue clusterStatsTimeout = newRandomTimeValue(); - private final TimeValue jobStatsTimeout = newRandomTimeValue(); - private final TimeValue recoveryTimeout = newRandomTimeValue(); - private final Boolean recoveryActiveOnly = randomBoolean(); - - @Override - protected Settings nodeSettings(int nodeOrdinal) { - return Settings.builder() - .put(super.nodeSettings(nodeOrdinal)) - .put(NetworkModule.HTTP_ENABLED.getKey(), false) - .put(monitoringSettings()) - .build(); - } - - @Override - protected Collection> nodePlugins() { - ArrayList> plugins = new ArrayList<>(super.nodePlugins()); - plugins.add(Netty4Plugin.class); // for http - return plugins; - } - - private Settings monitoringSettings() { - return Settings.builder() - .put(MonitoringSettings.INTERVAL.getKey(), interval) - .put(MonitoringSettings.INDEX_STATS_TIMEOUT.getKey(), indexStatsTimeout) - .putArray(MonitoringSettings.INDICES.getKey(), indices) - .put(MonitoringSettings.CLUSTER_STATE_TIMEOUT.getKey(), clusterStateTimeout) - .put(MonitoringSettings.CLUSTER_STATS_TIMEOUT.getKey(), clusterStatsTimeout) - .put(MonitoringSettings.JOB_STATS_TIMEOUT.getKey(), jobStatsTimeout) - .put(MonitoringSettings.INDEX_RECOVERY_TIMEOUT.getKey(), recoveryTimeout) - .put(MonitoringSettings.INDEX_RECOVERY_ACTIVE_ONLY.getKey(), recoveryActiveOnly) - .build(); - } - - public void testMonitoringSettings() throws Exception { - for (final MonitoringSettings monitoringSettings : internalCluster().getInstances(MonitoringSettings.class)) { - assertThat(monitoringSettings.indexStatsTimeout().millis(), equalTo(indexStatsTimeout.millis())); - assertArrayEquals(monitoringSettings.indices(), indices); - assertThat(monitoringSettings.clusterStateTimeout().millis(), equalTo(clusterStateTimeout.millis())); - assertThat(monitoringSettings.clusterStatsTimeout().millis(), equalTo(clusterStatsTimeout.millis())); - assertThat(monitoringSettings.jobStatsTimeout().millis(), equalTo(jobStatsTimeout.millis())); - assertThat(monitoringSettings.recoveryTimeout().millis(), equalTo(recoveryTimeout.millis())); - assertThat(monitoringSettings.recoveryActiveOnly(), equalTo(recoveryActiveOnly)); - } - - for (final MonitoringService service : internalCluster().getInstances(MonitoringService.class)) { - assertThat(service.getInterval().millis(), equalTo(interval.millis())); - - } - - logger.info("--> testing monitoring dynamic settings update"); - Settings.Builder transientSettings = Settings.builder(); - final Setting[] monitoringSettings = new Setting[]{ - MonitoringSettings.INDICES, - MonitoringSettings.INTERVAL, - MonitoringSettings.INDEX_RECOVERY_TIMEOUT, - MonitoringSettings.INDEX_STATS_TIMEOUT, - MonitoringSettings.INDEX_RECOVERY_ACTIVE_ONLY, - MonitoringSettings.CLUSTER_STATE_TIMEOUT, - MonitoringSettings.CLUSTER_STATS_TIMEOUT, - MonitoringSettings.JOB_STATS_TIMEOUT}; - for (Setting setting : monitoringSettings) { - if (setting.isDynamic()) { - if (setting.get(Settings.EMPTY) instanceof TimeValue) { - transientSettings.put(setting.getKey(), newRandomTimeValue().toString()); - } else if (setting.get(Settings.EMPTY) instanceof Boolean) { - transientSettings.put(setting.getKey(), randomBoolean()); - } else if (setting.get(Settings.EMPTY) instanceof List) { - transientSettings.putArray(setting.getKey(), randomStringArray()); - } else { - fail("unknown dynamic setting [" + setting + "]"); - } - } - } - - logger.error("--> updating settings"); - final Settings updatedSettings = transientSettings.build(); - assertAcked(prepareRandomUpdateSettings(updatedSettings).get()); - - logger.error("--> checking that the value has been correctly updated on all monitoring settings services"); - for (Setting setting : monitoringSettings) { - if (setting.isDynamic() == false) { - continue; - } - if (setting == MonitoringSettings.INTERVAL) { - for (final MonitoringService service : internalCluster().getInstances(MonitoringService.class)) { - assertEquals(service.getInterval(), setting.get(updatedSettings)); - } - } else { - for (final MonitoringSettings monitoringSettings1 : internalCluster().getInstances(MonitoringSettings.class)) { - if (setting == MonitoringSettings.INDEX_STATS_TIMEOUT) { - assertEquals(monitoringSettings1.indexStatsTimeout(), setting.get(updatedSettings)); - } else if (setting == MonitoringSettings.CLUSTER_STATS_TIMEOUT) { - assertEquals(monitoringSettings1.clusterStatsTimeout(), setting.get(updatedSettings)); - } else if (setting == MonitoringSettings.JOB_STATS_TIMEOUT) { - assertEquals(monitoringSettings1.jobStatsTimeout(), setting.get(updatedSettings)); - } else if (setting == MonitoringSettings.CLUSTER_STATE_TIMEOUT) { - assertEquals(monitoringSettings1.clusterStateTimeout(), setting.get(updatedSettings)); - } else if (setting == MonitoringSettings.INDEX_RECOVERY_TIMEOUT) { - assertEquals(monitoringSettings1.recoveryTimeout(), setting.get(updatedSettings)); - } else if (setting == MonitoringSettings.INDEX_RECOVERY_ACTIVE_ONLY) { - assertEquals(Boolean.valueOf(monitoringSettings1.recoveryActiveOnly()), setting.get(updatedSettings)); - } else if (setting == MonitoringSettings.INDICES) { - assertEquals(Arrays.asList(monitoringSettings1.indices()), setting.get(updatedSettings)); - } else { - fail("unable to check value for unknown dynamic setting [" + setting + "]"); - } - } - } - } - } - - private ClusterUpdateSettingsRequestBuilder prepareRandomUpdateSettings(Settings updateSettings) { - ClusterUpdateSettingsRequestBuilder requestBuilder = client().admin().cluster().prepareUpdateSettings(); - if (randomBoolean()) { - requestBuilder.setTransientSettings(updateSettings); - } else { - requestBuilder.setPersistentSettings(updateSettings); - } - return requestBuilder; - } - - private TimeValue newRandomTimeValue() { - return TimeValue.parseTimeValue(randomFrom("30m", "1h", "3h", "5h", "7h", "10h", "1d"), null, getClass().getSimpleName()); - } - - private String[] randomStringArray() { - final int size = scaledRandomIntBetween(1, 10); - String[] items = new String[size]; - - for (int i = 0; i < size; i++) { - items[i] = randomAlphaOfLength(5); - } - return items; - } -} diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MultiNodesStatsTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MultiNodesStatsTests.java index 41f7ef91ed2..d5ced18fc0c 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MultiNodesStatsTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/MultiNodesStatsTests.java @@ -14,7 +14,6 @@ import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.bucket.terms.StringTerms; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; import org.elasticsearch.test.ESIntegTestCase.Scope; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.collector.node.NodeStatsMonitoringDoc; import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; import org.junit.After; @@ -33,7 +32,7 @@ public class MultiNodesStatsTests extends MonitoringIntegTestCase { protected Settings nodeSettings(int nodeOrdinal) { return Settings.builder() .put(super.nodeSettings(nodeOrdinal)) - .put(MonitoringSettings.INTERVAL.getKey(), "-1") + .put(MonitoringService.INTERVAL.getKey(), "-1") .put("xpack.monitoring.exporters.default_local.type", "local") .build(); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/OldMonitoringIndicesBackwardsCompatibilityTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/OldMonitoringIndicesBackwardsCompatibilityTests.java index e08a45d33b7..a284c8f1d8a 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/OldMonitoringIndicesBackwardsCompatibilityTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/OldMonitoringIndicesBackwardsCompatibilityTests.java @@ -27,6 +27,7 @@ import org.elasticsearch.xpack.monitoring.collector.indices.IndexStatsMonitoring import org.elasticsearch.xpack.monitoring.collector.indices.IndicesStatsMonitoringDoc; import org.elasticsearch.xpack.monitoring.collector.node.NodeStatsMonitoringDoc; import org.elasticsearch.xpack.monitoring.collector.shards.ShardMonitoringDoc; +import org.elasticsearch.xpack.monitoring.exporter.Exporters; import org.hamcrest.Matcher; import org.joda.time.format.DateTimeFormat; @@ -63,9 +64,9 @@ public class OldMonitoringIndicesBackwardsCompatibilityTests extends AbstractOld Settings.Builder settings = Settings.builder().put(super.nodeSettings(ord)) .put(XPackSettings.MONITORING_ENABLED.getKey(), true) // Don't clean old monitoring indexes - we want to make sure we can load them - .put(MonitoringSettings.HISTORY_DURATION.getKey(), TimeValue.timeValueHours(1000 * 365 * 24).getStringRep()) + .put(Monitoring.HISTORY_DURATION.getKey(), TimeValue.timeValueHours(1000 * 365 * 24).getStringRep()) // Do not start monitoring exporters at startup - .put(MonitoringSettings.INTERVAL.getKey(), "-1"); + .put(MonitoringService.INTERVAL.getKey(), "-1"); if (httpExporter) { /* If we want to test the http exporter we have to create it but disable it. We need to create it so we don't use the default @@ -85,7 +86,7 @@ public class OldMonitoringIndicesBackwardsCompatibilityTests extends AbstractOld httpExporter.put("auth.username", SecuritySettingsSource.TEST_USER_NAME); httpExporter.put("auth.password", SecuritySettingsSource.TEST_PASSWORD); - settings.putProperties(httpExporter, k -> MonitoringSettings.EXPORTERS_SETTINGS.getKey() + "my_exporter." + k); + settings.putProperties(httpExporter, k -> Exporters.EXPORTERS_SETTINGS.getKey() + "my_exporter." + k); } @Override @@ -105,7 +106,7 @@ public class OldMonitoringIndicesBackwardsCompatibilityTests extends AbstractOld } // Monitoring can now start to collect new data - Settings.Builder settings = Settings.builder().put(MonitoringSettings.INTERVAL.getKey(), timeValueSeconds(3).getStringRep()); + Settings.Builder settings = Settings.builder().put(MonitoringService.INTERVAL.getKey(), timeValueSeconds(3).getStringRep()); assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings(settings).get()); final String prefix = ".monitoring-" + MonitoredSystem.ES.getSystem() + "-" + TEMPLATE_VERSION + "-"; @@ -167,7 +168,7 @@ public class OldMonitoringIndicesBackwardsCompatibilityTests extends AbstractOld if they have not been re created by some in flight monitoring bulk request */ internalCluster().getInstances(MonitoringService.class).forEach(MonitoringService::stop); - Settings.Builder settings = Settings.builder().put(MonitoringSettings.INTERVAL.getKey(), "-1"); + Settings.Builder settings = Settings.builder().put(MonitoringService.INTERVAL.getKey(), "-1"); if (httpExporter) { logger.info("--> Disabling http exporter after test"); setupHttpExporter(settings, null); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/AbstractIndicesCleanerTestCase.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/AbstractIndicesCleanerTestCase.java index 219879b5ee5..835fd85558c 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/AbstractIndicesCleanerTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/AbstractIndicesCleanerTestCase.java @@ -8,7 +8,8 @@ package org.elasticsearch.xpack.monitoring.cleaner; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.test.ESIntegTestCase.ClusterScope; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.Monitoring; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.exporter.Exporter; import org.elasticsearch.xpack.monitoring.exporter.Exporters; import org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils; @@ -29,7 +30,7 @@ public abstract class AbstractIndicesCleanerTestCase extends MonitoringIntegTest protected Settings nodeSettings(int nodeOrdinal) { Settings.Builder settings = Settings.builder() .put(super.nodeSettings(nodeOrdinal)) - .put(MonitoringSettings.INTERVAL.getKey(), "-1"); + .put(MonitoringService.INTERVAL.getKey(), "-1"); return settings.build(); } @@ -151,7 +152,7 @@ public abstract class AbstractIndicesCleanerTestCase extends MonitoringIntegTest public void testRetentionAsGlobalSetting() throws Exception { final int max = 10; final int retention = randomIntBetween(1, max); - internalCluster().startNode(Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), + internalCluster().startNode(Settings.builder().put(Monitoring.HISTORY_DURATION.getKey(), String.format(Locale.ROOT, "%dd", retention))); final DateTime now = now(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerServiceTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerServiceTests.java index 44dd709d0bf..96585f29753 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerServiceTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/cleaner/CleanerServiceTests.java @@ -12,7 +12,7 @@ import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.Monitoring; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.junit.After; @@ -40,7 +40,7 @@ public class CleanerServiceTests extends ESTestCase { @Before public void start() { - clusterSettings = new ClusterSettings(Settings.EMPTY, Collections.singleton(MonitoringSettings.HISTORY_DURATION)); + clusterSettings = new ClusterSettings(Settings.EMPTY, Collections.singleton(Monitoring.HISTORY_DURATION)); threadPool = new TestThreadPool("CleanerServiceTests"); } @@ -54,14 +54,14 @@ public class CleanerServiceTests extends ESTestCase { expectedException.expect(IllegalArgumentException.class); TimeValue expected = TimeValue.timeValueHours(1); - Settings settings = Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), expected.getStringRep()).build(); + Settings settings = Settings.builder().put(Monitoring.HISTORY_DURATION.getKey(), expected.getStringRep()).build(); new CleanerService(settings, clusterSettings, threadPool, licenseState); } public void testGetRetentionWithSettingWithUpdatesAllowed() { TimeValue expected = TimeValue.timeValueHours(25); - Settings settings = Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), expected.getStringRep()).build(); + Settings settings = Settings.builder().put(Monitoring.HISTORY_DURATION.getKey(), expected.getStringRep()).build(); when(licenseState.isUpdateRetentionAllowed()).thenReturn(true); @@ -73,7 +73,7 @@ public class CleanerServiceTests extends ESTestCase { public void testGetRetentionDefaultValueWithNoSettings() { when(licenseState.isUpdateRetentionAllowed()).thenReturn(true); - assertEquals(MonitoringSettings.HISTORY_DURATION.get(Settings.EMPTY), + assertEquals(Monitoring.HISTORY_DURATION.get(Settings.EMPTY), new CleanerService(Settings.EMPTY, clusterSettings, threadPool, licenseState).getRetention()); verify(licenseState).isUpdateRetentionAllowed(); @@ -81,11 +81,11 @@ public class CleanerServiceTests extends ESTestCase { public void testGetRetentionDefaultValueWithSettingsButUpdatesNotAllowed() { TimeValue notExpected = TimeValue.timeValueHours(25); - Settings settings = Settings.builder().put(MonitoringSettings.HISTORY_DURATION.getKey(), notExpected.getStringRep()).build(); + Settings settings = Settings.builder().put(Monitoring.HISTORY_DURATION.getKey(), notExpected.getStringRep()).build(); when(licenseState.isUpdateRetentionAllowed()).thenReturn(false); - assertEquals(MonitoringSettings.HISTORY_DURATION.get(Settings.EMPTY), + assertEquals(Monitoring.HISTORY_DURATION.get(Settings.EMPTY), new CleanerService(settings, clusterSettings, threadPool, licenseState).getRetention()); verify(licenseState).isUpdateRetentionAllowed(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/BaseCollectorTestCase.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/BaseCollectorTestCase.java index 23a230175c2..f0a154a262c 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/BaseCollectorTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/BaseCollectorTestCase.java @@ -12,12 +12,19 @@ import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.service.ClusterService; +import org.elasticsearch.common.settings.ClusterSettings; +import org.elasticsearch.common.settings.Setting; +import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; +import org.elasticsearch.common.unit.TimeValue; +import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.test.ESTestCase; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.Monitoring; import org.elasticsearch.xpack.security.InternalClient; +import java.util.function.Function; + import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -28,9 +35,9 @@ public abstract class BaseCollectorTestCase extends ESTestCase { protected ClusterState clusterState; protected DiscoveryNodes nodes; protected MetaData metaData; - protected MonitoringSettings monitoringSettings; protected XPackLicenseState licenseState; protected InternalClient client; + protected Settings settings; @Override public void setUp() throws Exception { @@ -40,9 +47,9 @@ public abstract class BaseCollectorTestCase extends ESTestCase { clusterState = mock(ClusterState.class); nodes = mock(DiscoveryNodes.class); metaData = mock(MetaData.class); - monitoringSettings = mock(MonitoringSettings.class); licenseState = mock(XPackLicenseState.class); client = mock(InternalClient.class); + settings = Settings.EMPTY; } protected void whenLocalNodeElectedMaster(final boolean electedMaster) { @@ -63,6 +70,28 @@ public abstract class BaseCollectorTestCase extends ESTestCase { when(metaData.clusterUUID()).thenReturn(clusterUUID); } + protected void withCollectionTimeout(final Setting collectionTimeout, final TimeValue timeout) { + withCollectionSetting(builder -> builder.put(collectionTimeout.getKey(), timeout.getStringRep())); + } + + protected void withCollectionIndices(final String[] collectionIndices) { + final String key = Collector.INDICES.getKey(); + if (collectionIndices != null) { + withCollectionSetting(builder -> builder.putArray(key, collectionIndices)); + } else { + withCollectionSetting(builder -> builder.putNull(key)); + } + } + + protected void withCollectionSetting(final Function builder) { + settings = Settings.builder() + .put(settings) + .put(builder.apply(Settings.builder()).build()) + .build(); + when(clusterService.getClusterSettings()) + .thenReturn(new ClusterSettings(settings, Sets.newHashSet(new Monitoring(settings, licenseState).getSettings()))); + } + protected static DiscoveryNode localNode(final String uuid) { return new DiscoveryNode(uuid, new TransportAddress(TransportAddress.META_ADDRESS, 9300), Version.CURRENT); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollectorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollectorTests.java index b44c3ff9299..1157c617d45 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollectorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/cluster/ClusterStatsCollectorTests.java @@ -25,7 +25,6 @@ import org.elasticsearch.xpack.action.XPackUsageResponse; import org.elasticsearch.xpack.logstash.Logstash; import org.elasticsearch.xpack.logstash.LogstashFeatureSet; import org.elasticsearch.xpack.monitoring.MonitoredSystem; -import org.elasticsearch.xpack.monitoring.MonitoringTestUtils; import org.elasticsearch.xpack.monitoring.collector.BaseCollectorTestCase; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; @@ -64,7 +63,7 @@ public class ClusterStatsCollectorTests extends BaseCollectorTestCase { whenLocalNodeElectedMaster(false); final ClusterStatsCollector collector = - new ClusterStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client, licenseService); + new ClusterStatsCollector(Settings.EMPTY, clusterService, licenseState, client, licenseService); assertThat(collector.shouldCollect(), is(false)); verify(nodes).isLocalNodeElectedMaster(); @@ -74,13 +73,16 @@ public class ClusterStatsCollectorTests extends BaseCollectorTestCase { whenLocalNodeElectedMaster(true); final ClusterStatsCollector collector = - new ClusterStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client, licenseService); + new ClusterStatsCollector(Settings.EMPTY, clusterService, licenseState, client, licenseService); assertThat(collector.shouldCollect(), is(true)); verify(nodes).isLocalNodeElectedMaster(); } public void testDoCollect() throws Exception { + final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(1, 120)); + withCollectionTimeout(ClusterStatsCollector.CLUSTER_STATS_TIMEOUT, timeout); + whenLocalNodeElectedMaster(true); final String clusterName = randomAlphaOfLength(10); @@ -102,9 +104,6 @@ public class ClusterStatsCollectorTests extends BaseCollectorTestCase { .build(); when(licenseService.getLicense()).thenReturn(license); - final TimeValue timeout = mock(TimeValue.class); - when(monitoringSettings.clusterStatsTimeout()).thenReturn(timeout); - final ClusterStatsResponse mockClusterStatsResponse = mock(ClusterStatsResponse.class); final ClusterHealthStatus clusterStatus = randomFrom(ClusterHealthStatus.values()); @@ -137,7 +136,8 @@ public class ClusterStatsCollectorTests extends BaseCollectorTestCase { when(xPackUsageFuture.actionGet()).thenReturn(xPackUsageResponse); final ClusterStatsCollector collector = - new ClusterStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client, licenseService); + new ClusterStatsCollector(Settings.EMPTY, clusterService, licenseState, client, licenseService); + assertEquals(timeout, collector.getCollectionTimeout()); final Collection results = collector.doCollect(node); assertEquals(1, results.size()); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollectorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollectorTests.java index 8ad669b25ba..2268c51814f 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollectorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexRecoveryCollectorTests.java @@ -16,6 +16,7 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.routing.RecoverySource; import org.elasticsearch.cluster.routing.ShardRouting; import org.elasticsearch.cluster.routing.UnassignedInfo; +import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.shard.ShardId; @@ -53,8 +54,7 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(false); whenLocalNodeElectedMaster(randomBoolean()); - final IndexRecoveryCollector collector = - new IndexRecoveryCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexRecoveryCollector collector = new IndexRecoveryCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -65,8 +65,7 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { // this controls the blockage whenLocalNodeElectedMaster(false); - final IndexRecoveryCollector collector = - new IndexRecoveryCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexRecoveryCollector collector = new IndexRecoveryCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -77,8 +76,7 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(true); whenLocalNodeElectedMaster(true); - final IndexRecoveryCollector collector = - new IndexRecoveryCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexRecoveryCollector collector = new IndexRecoveryCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(true)); verify(licenseState).isMonitoringAllowed(); @@ -86,6 +84,9 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { } public void testDoCollect() throws Exception { + final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(1, 120)); + withCollectionTimeout(IndexRecoveryCollector.INDEX_RECOVERY_TIMEOUT, timeout); + whenLocalNodeElectedMaster(true); final String clusterName = randomAlphaOfLength(10); @@ -100,19 +101,18 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { final MonitoringDoc.Node node = randomMonitoringNode(random()); final boolean recoveryOnly = randomBoolean(); - when(monitoringSettings.recoveryActiveOnly()).thenReturn(recoveryOnly); + withCollectionSetting(builder -> builder.put(IndexRecoveryCollector.INDEX_RECOVERY_ACTIVE_ONLY.getKey(), recoveryOnly)); final String[] indices; if (randomBoolean()) { - indices = null; + indices = randomBoolean() ? null : Strings.EMPTY_ARRAY; } else { indices = new String[randomIntBetween(1, 5)]; for (int i = 0; i < indices.length; i++) { indices[i] = randomAlphaOfLengthBetween(5, 10); } } - when(monitoringSettings.indices()).thenReturn(indices); - when(monitoringSettings.recoveryTimeout()).thenReturn(TimeValue.timeValueSeconds(12)); + withCollectionIndices(indices); final int nbRecoveries = randomBoolean() ? 0 : randomIntBetween(1, 3); final Map> recoveryStates = new HashMap<>(); @@ -130,9 +130,6 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { final RecoveryResponse recoveryResponse = new RecoveryResponse(randomInt(), randomInt(), randomInt(), randomBoolean(), recoveryStates, emptyList()); - final TimeValue timeout = mock(TimeValue.class); - when(monitoringSettings.recoveryTimeout()).thenReturn(timeout); - final RecoveryRequestBuilder recoveryRequestBuilder = spy(new RecoveryRequestBuilder(mock(ElasticsearchClient.class), RecoveryAction.INSTANCE)); doReturn(recoveryResponse).when(recoveryRequestBuilder).get(eq(timeout)); @@ -146,8 +143,17 @@ public class IndexRecoveryCollectorTests extends BaseCollectorTestCase { final Client client = mock(Client.class); when(client.admin()).thenReturn(adminClient); - final IndexRecoveryCollector collector = - new IndexRecoveryCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexRecoveryCollector collector = new IndexRecoveryCollector(Settings.EMPTY, clusterService, licenseState, client); + assertEquals(timeout, collector.getCollectionTimeout()); + assertEquals(recoveryOnly, collector.getActiveRecoveriesOnly()); + + if (indices != null) { + assertArrayEquals(indices, collector.getCollectionIndices()); + } else { + // Collection indices has a default value equals to emptyList(), + // so it won't return a null indices array + assertArrayEquals(Strings.EMPTY_ARRAY, collector.getCollectionIndices()); + } final Collection results = collector.doCollect(node); verify(indicesAdminClient).prepareRecoveries(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollectorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollectorTests.java index 53986e84c27..db0e8ec4744 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollectorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/indices/IndexStatsCollectorTests.java @@ -43,8 +43,7 @@ public class IndexStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(false); whenLocalNodeElectedMaster(randomBoolean()); - final IndexStatsCollector collector = - new IndexStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexStatsCollector collector = new IndexStatsCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -55,8 +54,7 @@ public class IndexStatsCollectorTests extends BaseCollectorTestCase { // this controls the blockage whenLocalNodeElectedMaster(false); - final IndexStatsCollector collector = - new IndexStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexStatsCollector collector = new IndexStatsCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -67,8 +65,7 @@ public class IndexStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(true); whenLocalNodeElectedMaster(true); - final IndexStatsCollector collector = - new IndexStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexStatsCollector collector = new IndexStatsCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(true)); verify(licenseState).isMonitoringAllowed(); @@ -76,6 +73,9 @@ public class IndexStatsCollectorTests extends BaseCollectorTestCase { } public void testDoCollect() throws Exception { + final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(1, 120)); + withCollectionTimeout(IndexStatsCollector.INDEX_STATS_TIMEOUT, timeout); + whenLocalNodeElectedMaster(true); final String clusterName = randomAlphaOfLength(10); @@ -86,9 +86,6 @@ public class IndexStatsCollectorTests extends BaseCollectorTestCase { final MonitoringDoc.Node node = randomMonitoringNode(random()); - final TimeValue timeout = mock(TimeValue.class); - when(monitoringSettings.indexStatsTimeout()).thenReturn(timeout); - final Map indicesStats = new HashMap<>(); final int indices = randomIntBetween(0, 10); for (int i = 0; i < indices; i++) { @@ -114,8 +111,8 @@ public class IndexStatsCollectorTests extends BaseCollectorTestCase { final Client client = mock(Client.class); when(client.admin()).thenReturn(adminClient); - final IndexStatsCollector collector = - new IndexStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final IndexStatsCollector collector = new IndexStatsCollector(Settings.EMPTY, clusterService, licenseState, client); + assertEquals(timeout, collector.getCollectionTimeout()); final Collection results = collector.doCollect(node); verify(indicesAdminClient).prepareStats(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollectorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollectorTests.java index 03461eedcc1..70f9accc8cb 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollectorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/ml/JobStatsCollectorTests.java @@ -47,7 +47,7 @@ public class JobStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(false); when(licenseState.isMachineLearningAllowed()).thenReturn(mlAllowed); - final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, monitoringSettings, licenseState, client); + final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); @@ -63,7 +63,7 @@ public class JobStatsCollectorTests extends BaseCollectorTestCase { // this controls the blockage whenLocalNodeElectedMaster(false); - final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, monitoringSettings, licenseState, client); + final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); @@ -78,7 +78,7 @@ public class JobStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMachineLearningAllowed()).thenReturn(randomBoolean()); whenLocalNodeElectedMaster(randomBoolean()); - final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, monitoringSettings, licenseState, client); + final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); @@ -93,7 +93,7 @@ public class JobStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMachineLearningAllowed()).thenReturn(false); whenLocalNodeElectedMaster(randomBoolean()); - final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, monitoringSettings, licenseState, client); + final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); @@ -107,7 +107,7 @@ public class JobStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMachineLearningAllowed()).thenReturn(true); whenLocalNodeElectedMaster(true); - final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, monitoringSettings, licenseState, client); + final JobStatsCollector collector = new JobStatsCollector(settings, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(true)); @@ -115,20 +115,20 @@ public class JobStatsCollectorTests extends BaseCollectorTestCase { } public void testDoCollect() throws Exception { - final TimeValue timeout = mock(TimeValue.class); final MetaData metaData = mock(MetaData.class); final String clusterUuid = randomAlphaOfLength(5); final MonitoringDoc.Node node = randomMonitoringNode(random()); final MachineLearningClient client = mock(MachineLearningClient.class); - when(monitoringSettings.jobStatsTimeout()).thenReturn(timeout); + final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(1, 120)); + withCollectionTimeout(JobStatsCollector.JOB_STATS_TIMEOUT, timeout); when(clusterService.state()).thenReturn(clusterState); when(clusterState.metaData()).thenReturn(metaData); when(metaData.clusterUUID()).thenReturn(clusterUuid); - final JobStatsCollector collector = - new JobStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final JobStatsCollector collector = new JobStatsCollector(Settings.EMPTY, clusterService, licenseState, client); + assertEquals(timeout, collector.getCollectionTimeout()); final List jobStats = mockJobStats(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollectorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollectorTests.java index c7c67db14d7..66ba843e41f 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollectorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/node/NodeStatsCollectorTests.java @@ -15,6 +15,7 @@ import org.elasticsearch.client.AdminClient; import org.elasticsearch.client.Client; import org.elasticsearch.client.ClusterAdminClient; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.xpack.monitoring.MonitoredSystem; import org.elasticsearch.xpack.monitoring.collector.BaseCollectorTestCase; import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc; @@ -41,8 +42,7 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(false); whenLocalNodeElectedMaster(randomBoolean()); - final NodeStatsCollector collector = - new NodeStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final NodeStatsCollector collector = new NodeStatsCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -52,8 +52,7 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(true); whenLocalNodeElectedMaster(true); - final NodeStatsCollector collector = - new NodeStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final NodeStatsCollector collector = new NodeStatsCollector(Settings.EMPTY, clusterService, licenseState, client); assertThat(collector.shouldCollect(), is(true)); verify(licenseState).isMonitoringAllowed(); @@ -62,6 +61,9 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { public void testDoCollectWithFailures() throws Exception { when(licenseState.isMonitoringAllowed()).thenReturn(true); + final TimeValue timeout = TimeValue.parseTimeValue(randomPositiveTimeValue(), NodeStatsCollectorTests.class.getName()); + withCollectionTimeout(NodeStatsCollector.NODE_STATS_TIMEOUT, timeout); + final NodesStatsResponse nodesStatsResponse = mock(NodesStatsResponse.class); when(nodesStatsResponse.hasFailures()).thenReturn(true); @@ -69,10 +71,10 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { when(nodesStatsResponse.failures()).thenReturn(Collections.singletonList(exception)); final Client client = mock(Client.class); - thenReturnNodeStats(client, nodesStatsResponse); + thenReturnNodeStats(client, timeout, nodesStatsResponse); - final NodeStatsCollector collector = - new NodeStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final NodeStatsCollector collector = new NodeStatsCollector(Settings.EMPTY, clusterService, licenseState, client); + assertEquals(timeout, collector.getCollectionTimeout()); final FailedNodeException e = expectThrows(FailedNodeException.class, () -> collector.doCollect(randomMonitoringNode(random()))); assertEquals(exception, e); @@ -81,6 +83,9 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { public void testDoCollect() throws Exception { when(licenseState.isMonitoringAllowed()).thenReturn(true); + final TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(1, 120)); + withCollectionTimeout(NodeStatsCollector.NODE_STATS_TIMEOUT, timeout); + final boolean isMaster = randomBoolean(); whenLocalNodeElectedMaster(isMaster); @@ -99,10 +104,10 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { when(nodeStats.getTimestamp()).thenReturn(timestamp); final Client client = mock(Client.class); - thenReturnNodeStats(client, nodesStatsResponse); + thenReturnNodeStats(client, timeout, nodesStatsResponse); - final NodeStatsCollector collector = - new NodeStatsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState, client); + final NodeStatsCollector collector = new NodeStatsCollector(Settings.EMPTY, clusterService, licenseState, client); + assertEquals(timeout, collector.getCollectionTimeout()); final Collection results = collector.doCollect(node); assertEquals(1, results.size()); @@ -124,10 +129,10 @@ public class NodeStatsCollectorTests extends BaseCollectorTestCase { assertThat(document.isMlockall(), equalTo(BootstrapInfo.isMemoryLocked())); } - private void thenReturnNodeStats(final Client client, final NodesStatsResponse nodesStatsResponse) { + private void thenReturnNodeStats(final Client client, final TimeValue timeout, final NodesStatsResponse nodesStatsResponse) { @SuppressWarnings("unchecked") final ActionFuture future = (ActionFuture) mock(ActionFuture.class); - when(future.actionGet(eq(monitoringSettings.nodeStatsTimeout()))).thenReturn(nodesStatsResponse); + when(future.actionGet(eq(timeout))).thenReturn(nodesStatsResponse); final ClusterAdminClient clusterAdminClient = mock(ClusterAdminClient.class); when(clusterAdminClient.nodesStats(any(NodesStatsRequest.class))).thenReturn(future); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollectorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollectorTests.java index e817b2c2e18..682737ca0bb 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollectorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/collector/shards/ShardsCollectorTests.java @@ -47,7 +47,7 @@ public class ShardsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(false); whenLocalNodeElectedMaster(randomBoolean()); - final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState); + final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, licenseState); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -58,7 +58,7 @@ public class ShardsCollectorTests extends BaseCollectorTestCase { // this controls the blockage whenLocalNodeElectedMaster(false); - final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState); + final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, licenseState); assertThat(collector.shouldCollect(), is(false)); verify(licenseState).isMonitoringAllowed(); @@ -69,7 +69,7 @@ public class ShardsCollectorTests extends BaseCollectorTestCase { when(licenseState.isMonitoringAllowed()).thenReturn(true); whenLocalNodeElectedMaster(true); - final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState); + final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, licenseState); assertThat(collector.shouldCollect(), is(true)); verify(licenseState).isMonitoringAllowed(); @@ -79,7 +79,7 @@ public class ShardsCollectorTests extends BaseCollectorTestCase { public void testDoCollectWhenNoClusterState() throws Exception { when(clusterService.state()).thenReturn(null); - final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState); + final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, licenseState); final Collection results = collector.doCollect(randomMonitoringNode(random())); assertThat(results, notNullValue()); @@ -98,7 +98,7 @@ public class ShardsCollectorTests extends BaseCollectorTestCase { when(clusterState.stateUUID()).thenReturn(stateUUID); final String[] indices = randomFrom(NONE, Strings.EMPTY_ARRAY, new String[]{"_all"}, new String[]{"_index*"}); - when(monitoringSettings.indices()).thenReturn(indices); + withCollectionIndices(indices); final RoutingTable routingTable = mockRoutingTable(); when(clusterState.routingTable()).thenReturn(routingTable); @@ -108,7 +108,9 @@ public class ShardsCollectorTests extends BaseCollectorTestCase { when(nodes.get(eq("_current"))).thenReturn(localNode); when(clusterState.getNodes()).thenReturn(nodes); - final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, monitoringSettings, licenseState); + final ShardsCollector collector = new ShardsCollector(Settings.EMPTY, clusterService, licenseState); + assertNull(collector.getCollectionTimeout()); + assertArrayEquals(indices, collector.getCollectionIndices()); final Collection results = collector.doCollect(node); assertThat(results, notNullValue()); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/ExportersTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/ExportersTests.java index 78b376cf906..004c1ef6ff1 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/ExportersTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/ExportersTests.java @@ -19,8 +19,7 @@ import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.monitoring.MonitoredSystem; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; -import org.elasticsearch.xpack.monitoring.action.MonitoringBulkDoc; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.cleaner.CleanerService; import org.elasticsearch.xpack.monitoring.exporter.local.LocalExporter; import org.elasticsearch.xpack.security.InternalClient; @@ -40,6 +39,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import static java.util.Collections.singleton; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; @@ -75,7 +75,7 @@ public class ExportersTests extends ESTestCase { // default state.version() will be 0, which is "valid" state = mock(ClusterState.class); clusterSettings = new ClusterSettings(Settings.EMPTY, - new HashSet<>(Arrays.asList(MonitoringSettings.INTERVAL, MonitoringSettings.EXPORTERS_SETTINGS))); + new HashSet<>(Arrays.asList(MonitoringService.INTERVAL, Exporters.EXPORTERS_SETTINGS))); when(clusterService.getClusterSettings()).thenReturn(clusterSettings); when(clusterService.state()).thenReturn(state); @@ -180,7 +180,7 @@ public class ExportersTests extends ESTestCase { .put("xpack.monitoring.exporters._name0.type", "_type") .put("xpack.monitoring.exporters._name1.type", "_type") .build(); - clusterSettings = new ClusterSettings(nodeSettings, new HashSet<>(Arrays.asList(MonitoringSettings.EXPORTERS_SETTINGS))); + clusterSettings = new ClusterSettings(nodeSettings, singleton(Exporters.EXPORTERS_SETTINGS)); when(clusterService.getClusterSettings()).thenReturn(clusterSettings); exporters = new Exporters(nodeSettings, factories, clusterService, licenseState, threadContext) { diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java index bc1dcc40554..b75a3cd38e9 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/http/HttpExporterIT.java @@ -29,7 +29,7 @@ import org.elasticsearch.test.ESIntegTestCase.Scope; import org.elasticsearch.test.http.MockRequest; import org.elasticsearch.test.http.MockResponse; import org.elasticsearch.test.http.MockWebServer; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.MonitoringTestUtils; import org.elasticsearch.xpack.monitoring.collector.indices.IndexRecoveryMonitoringDoc; import org.elasticsearch.xpack.monitoring.exporter.ClusterAlertsUtil; @@ -107,7 +107,7 @@ public class HttpExporterIT extends MonitoringIntegTestCase { // we make an exporter on demand per test return Settings.builder() .put(super.nodeSettings(nodeOrdinal)) - .put(MonitoringSettings.INTERVAL.getKey(), "-1") + .put(MonitoringService.INTERVAL.getKey(), "-1") .put("xpack.monitoring.exporters._http.type", "http") .put("xpack.monitoring.exporters._http.enabled", false) .build(); diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTestCase.java index e6c9e5aab46..b4373a43646 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTestCase.java @@ -11,7 +11,7 @@ import org.elasticsearch.license.XPackLicenseState; import org.elasticsearch.threadpool.TestThreadPool; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.XPackSettings; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.cleaner.CleanerService; import org.elasticsearch.xpack.monitoring.exporter.Exporter; import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; @@ -65,7 +65,7 @@ public abstract class LocalExporterIntegTestCase extends MonitoringIntegTestCase protected Settings localExporterSettings() { return Settings.builder() - .put(MonitoringSettings.INTERVAL.getKey(), "-1") + .put(MonitoringService.INTERVAL.getKey(), "-1") .put("xpack.monitoring.exporters." + exporterName + ".type", LocalExporter.TYPE) .put("xpack.monitoring.exporters." + exporterName + ".enabled", false) .put("xpack.monitoring.exporters." + exporterName + "." + CLUSTER_ALERTS_MANAGEMENT_SETTING, useClusterAlerts()) diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTests.java index 637f083c794..e5a8dfc1f1c 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/exporter/local/LocalExporterIntegTests.java @@ -26,7 +26,7 @@ import org.elasticsearch.search.aggregations.metrics.max.Max; import org.elasticsearch.test.ESIntegTestCase; import org.elasticsearch.xpack.XPackClient; import org.elasticsearch.xpack.monitoring.MonitoredSystem; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.MonitoringTestUtils; import org.elasticsearch.xpack.monitoring.action.MonitoringBulkDoc; import org.elasticsearch.xpack.monitoring.action.MonitoringBulkRequestBuilder; @@ -71,7 +71,7 @@ public class LocalExporterIntegTests extends LocalExporterIntegTestCase { private void stopMonitoring() throws Exception { // Now disabling the monitoring service, so that no more collection are started assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings( - Settings.builder().putNull(MonitoringSettings.INTERVAL.getKey()) + Settings.builder().putNull(MonitoringService.INTERVAL.getKey()) .putNull("xpack.monitoring.exporters._local.enabled") .putNull("xpack.monitoring.exporters._local.index.name.time_format"))); } @@ -126,7 +126,7 @@ public class LocalExporterIntegTests extends LocalExporterIntegTestCase { // monitoring service is started exporterSettings = Settings.builder() - .put(MonitoringSettings.INTERVAL.getKey(), 3L, TimeUnit.SECONDS); + .put(MonitoringService.INTERVAL.getKey(), 3L, TimeUnit.SECONDS); assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings(exporterSettings)); final int numNodes = internalCluster().getNodeNames().length; diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringInternalClientTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringInternalClientTests.java index 7813035767c..fe78753ba30 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringInternalClientTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringInternalClientTests.java @@ -10,7 +10,7 @@ import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.collect.Tuple; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; import org.elasticsearch.xpack.security.InternalClient; @@ -24,7 +24,7 @@ public class MonitoringInternalClientTests extends MonitoringIntegTestCase { protected Settings nodeSettings(int nodeOrdinal) { return Settings.builder() .put(super.nodeSettings(nodeOrdinal)) - .put(MonitoringSettings.INTERVAL.getKey(), "-1") + .put(MonitoringService.INTERVAL.getKey(), "-1") .build(); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringSettingsFilterTests.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringSettingsFilterTests.java index b9d2d836e34..1d95f694682 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringSettingsFilterTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/security/MonitoringSettingsFilterTests.java @@ -14,7 +14,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.plugins.Plugin; import org.elasticsearch.transport.Netty4Plugin; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; +import org.elasticsearch.xpack.monitoring.MonitoringService; import org.elasticsearch.xpack.monitoring.test.MonitoringIntegTestCase; import java.util.ArrayList; @@ -35,7 +35,7 @@ public class MonitoringSettingsFilterTests extends MonitoringIntegTestCase { return Settings.builder() .put(super.nodeSettings(nodeOrdinal)) .put(NetworkModule.HTTP_ENABLED.getKey(), true) - .put(MonitoringSettings.INTERVAL.getKey(), "-1") + .put(MonitoringService.INTERVAL.getKey(), "-1") .put("xpack.monitoring.exporters._http.type", "http") .put("xpack.monitoring.exporters._http.enabled", false) .put("xpack.monitoring.exporters._http.auth.username", "_user") diff --git a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/test/MonitoringIntegTestCase.java b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/test/MonitoringIntegTestCase.java index 7be94498f76..f906a5a6607 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/monitoring/test/MonitoringIntegTestCase.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/monitoring/test/MonitoringIntegTestCase.java @@ -34,7 +34,6 @@ import org.elasticsearch.xpack.XPackPlugin; import org.elasticsearch.xpack.XPackSettings; import org.elasticsearch.xpack.ml.MachineLearning; import org.elasticsearch.xpack.monitoring.MonitoringService; -import org.elasticsearch.xpack.monitoring.MonitoringSettings; import org.elasticsearch.xpack.monitoring.client.MonitoringClient; import org.elasticsearch.xpack.monitoring.exporter.ClusterAlertsUtil; import org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils; @@ -404,7 +403,7 @@ public abstract class MonitoringIntegTestCase extends ESIntegTestCase { protected void updateMonitoringInterval(long value, TimeUnit timeUnit) { assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings( - Settings.builder().put(MonitoringSettings.INTERVAL.getKey(), value, timeUnit))); + Settings.builder().put(MonitoringService.INTERVAL.getKey(), value, timeUnit))); } /** security related settings */ From c46e09902d4b75154e7c3bb3a65ffb1e124fca13 Mon Sep 17 00:00:00 2001 From: Dimitris Athanasiou Date: Tue, 26 Sep 2017 11:46:01 +0100 Subject: [PATCH 6/9] [ML] Fix close job when the process has not launched yet (elastic/x-pack-elasticsearch#2616) If a job close is requested after a job was opened but before its process was launched, the job close returns successfully without doing anything. The result is that the process hangs around. This has been causing test failures as documented int elastic/x-pack-elasticsearch#2360 and elastic/x-pack-elasticsearch#1270. This commit fixes this problem by refactoring the AutodetectProcessManager. It introduces a state pattern to make clear the states of the process and it uses locking to ensure a close waits for the job process to be created. relates elastic/x-pack-elasticsearch#1270 Original commit: elastic/x-pack-elasticsearch@ff858bd1362abc0b9d6ce887ce44b35d1cdc26ab --- .../autodetect/AutodetectCommunicator.java | 9 +- .../autodetect/AutodetectProcessManager.java | 172 ++++++++------- .../NativeAutodetectProcessFactory.java | 2 +- .../process/autodetect/ProcessContext.java | 195 ++++++++++++++++++ .../AutodetectCommunicatorTests.java | 4 +- .../AutodetectProcessManagerTests.java | 1 - 6 files changed, 295 insertions(+), 88 deletions(-) create mode 100644 plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/ProcessContext.java diff --git a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicator.java b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicator.java index 0dcc25c8825..04624ab05da 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicator.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicator.java @@ -15,7 +15,6 @@ import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentType; -import org.elasticsearch.xpack.ml.action.OpenJobAction.JobTask; import org.elasticsearch.xpack.ml.job.config.DataDescription; import org.elasticsearch.xpack.ml.job.config.Job; import org.elasticsearch.xpack.ml.job.config.JobUpdate; @@ -56,7 +55,6 @@ public class AutodetectCommunicator implements Closeable { private static final Duration FLUSH_PROCESS_CHECK_FREQUENCY = Duration.ofSeconds(1); private final Job job; - private final JobTask jobTask; private final AutodetectProcess autodetectProcess; private final StateStreamer stateStreamer; private final DataCountsReporter dataCountsReporter; @@ -66,12 +64,11 @@ public class AutodetectCommunicator implements Closeable { private final NamedXContentRegistry xContentRegistry; private volatile boolean processKilled; - AutodetectCommunicator(Job job, JobTask jobTask, AutodetectProcess process, StateStreamer stateStreamer, + AutodetectCommunicator(Job job, AutodetectProcess process, StateStreamer stateStreamer, DataCountsReporter dataCountsReporter, AutoDetectResultProcessor autoDetectResultProcessor, Consumer onFinishHandler, NamedXContentRegistry xContentRegistry, ExecutorService autodetectWorkerExecutor) { this.job = job; - this.jobTask = jobTask; this.autodetectProcess = process; this.stateStreamer = stateStreamer; this.dataCountsReporter = dataCountsReporter; @@ -261,10 +258,6 @@ public class AutodetectCommunicator implements Closeable { } } - public JobTask getJobTask() { - return jobTask; - } - public ZonedDateTime getProcessStartTime() { return autodetectProcess.getProcessStartTime(); } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java index 996d0a76586..444196c6a57 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManager.java @@ -17,7 +17,6 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.AbstractRunnable; import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; import org.elasticsearch.common.util.concurrent.ThreadContext; -import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; @@ -50,7 +49,6 @@ import org.elasticsearch.xpack.ml.job.process.normalizer.NormalizerFactory; import org.elasticsearch.xpack.ml.job.process.normalizer.Renormalizer; import org.elasticsearch.xpack.ml.job.process.normalizer.ScoresUpdater; import org.elasticsearch.xpack.ml.job.process.normalizer.ShortCircuitingRenormalizer; -import org.elasticsearch.xpack.ml.job.results.Forecast; import org.elasticsearch.xpack.ml.notifications.Auditor; import org.elasticsearch.xpack.ml.utils.ExceptionsHelper; import org.elasticsearch.xpack.persistent.PersistentTasksCustomMetaData.PersistentTask; @@ -59,7 +57,6 @@ import java.io.IOException; import java.io.InputStream; import java.time.Duration; import java.time.ZonedDateTime; -import java.util.Arrays; import java.util.Date; import java.util.Iterator; import java.util.List; @@ -105,8 +102,7 @@ public class AutodetectProcessManager extends AbstractComponent { private final JobResultsPersister jobResultsPersister; private final JobDataCountsPersister jobDataCountsPersister; - private final ConcurrentMap autoDetectCommunicatorByOpenJob = new ConcurrentHashMap<>(); - private final ConcurrentMap autoDetectCommunicatorByClosingJob = new ConcurrentHashMap<>(); + private final ConcurrentMap processByAllocation = new ConcurrentHashMap<>(); private final int maxAllowedRunningJobs; @@ -134,53 +130,37 @@ public class AutodetectProcessManager extends AbstractComponent { } public synchronized void closeAllJobsOnThisNode(String reason) throws IOException { - int numJobs = autoDetectCommunicatorByOpenJob.size(); + int numJobs = processByAllocation.size(); if (numJobs != 0) { logger.info("Closing [{}] jobs, because [{}]", numJobs, reason); - for (AutodetectCommunicator communicator : autoDetectCommunicatorByOpenJob.values()) { - closeJob(communicator.getJobTask(), false, reason); + for (ProcessContext process : processByAllocation.values()) { + closeJob(process.getJobTask(), false, reason); } } } public void killProcess(JobTask jobTask, boolean awaitCompletion, String reason) { - String extraInfo; - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.remove(jobTask.getAllocationId()); - if (communicator == null) { - extraInfo = " while closing"; - // if there isn't an open job, check for a closing job - communicator = autoDetectCommunicatorByClosingJob.remove(jobTask.getAllocationId()); - } else { - extraInfo = ""; - } - if (communicator != null) { - if (reason == null) { - logger.info("Killing job [{}]{}", jobTask.getJobId(), extraInfo); - } else { - logger.info("Killing job [{}]{}, because [{}]", jobTask.getJobId(), extraInfo, reason); - } - killProcess(communicator, jobTask.getJobId(), awaitCompletion, true); + ProcessContext processContext = processByAllocation.remove(jobTask.getAllocationId()); + if (processContext != null) { + processContext.newKillBuilder() + .setAwaitCompletion(awaitCompletion) + .setFinish(true) + .setReason(reason) + .kill(); } } public void killAllProcessesOnThisNode() { - // first kill open jobs, then closing jobs - for (Iterator iter : Arrays.asList(autoDetectCommunicatorByOpenJob.values().iterator(), - autoDetectCommunicatorByClosingJob.values().iterator())) { - while (iter.hasNext()) { - AutodetectCommunicator communicator = iter.next(); - iter.remove(); - killProcess(communicator, communicator.getJobTask().getJobId(), false, false); - } - } - } - - private void killProcess(AutodetectCommunicator communicator, String jobId, boolean awaitCompletion, boolean finish) { - try { - communicator.killProcess(awaitCompletion, finish); - } catch (IOException e) { - logger.error("[{}] Failed to kill autodetect process for job", jobId); + Iterator iterator = processByAllocation.values().iterator(); + while (iterator.hasNext()) { + ProcessContext processContext = iterator.next(); + processContext.newKillBuilder() + .setAwaitCompletion(false) + .setFinish(false) + .setSilent(true) + .kill(); + iterator.remove(); } } @@ -205,7 +185,7 @@ public class AutodetectProcessManager extends AbstractComponent { */ public void processData(JobTask jobTask, InputStream input, XContentType xContentType, DataLoadParams params, BiConsumer handler) { - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()); + AutodetectCommunicator communicator = getOpenAutodetectCommunicator(jobTask); if (communicator == null) { throw ExceptionsHelper.conflictStatusException("Cannot process data because job [" + jobTask.getJobId() + "] is not open"); } @@ -223,7 +203,7 @@ public class AutodetectProcessManager extends AbstractComponent { */ public void flushJob(JobTask jobTask, FlushJobParams params, ActionListener handler) { logger.debug("Flushing job {}", jobTask.getJobId()); - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()); + AutodetectCommunicator communicator = getOpenAutodetectCommunicator(jobTask); if (communicator == null) { String message = String.format(Locale.ROOT, "Cannot flush because job [%s] is not open", jobTask.getJobId()); logger.debug(message); @@ -250,7 +230,7 @@ public class AutodetectProcessManager extends AbstractComponent { */ public void forecastJob(JobTask jobTask, ForecastParams params, Consumer handler) { logger.debug("Forecasting job {}", jobTask.getJobId()); - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()); + AutodetectCommunicator communicator = getOpenAutodetectCommunicator(jobTask); if (communicator == null) { String message = String.format(Locale.ROOT, "Cannot forecast because job [%s] is not open", jobTask.getJobId()); logger.debug(message); @@ -271,7 +251,7 @@ public class AutodetectProcessManager extends AbstractComponent { public void writeUpdateProcessMessage(JobTask jobTask, List updates, ModelPlotConfig config, Consumer handler) { - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()); + AutodetectCommunicator communicator = getOpenAutodetectCommunicator(jobTask); if (communicator == null) { String message = "Cannot process update model debug config because job [" + jobTask.getJobId() + "] is not open"; logger.debug(message); @@ -298,6 +278,7 @@ public class AutodetectProcessManager extends AbstractComponent { } logger.info("Opening job [{}]", jobId); + processByAllocation.putIfAbsent(jobTask.getAllocationId(), new ProcessContext(jobTask)); jobProvider.getAutodetectParams(job, params -> { // We need to fork, otherwise we restore model state from a network thread (several GET api calls): threadPool.executor(MachineLearning.UTILITY_THREAD_POOL_NAME).execute(new AbstractRunnable() { @@ -308,19 +289,29 @@ public class AutodetectProcessManager extends AbstractComponent { @Override protected void doRun() throws Exception { + ProcessContext processContext = processByAllocation.get(jobTask.getAllocationId()); + if (processContext == null) { + logger.debug("Aborted opening job [{}] as it has been closed", jobId); + return; + } + if (processContext.getState() != ProcessContext.ProcessStateName.NOT_RUNNING) { + logger.debug("Cannot open job [{}] when its state is [{}]", jobId, processContext.getState().getClass().getName()); + return; + } + try { - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.computeIfAbsent(jobTask.getAllocationId(), - id -> create(jobTask, params, handler)); - communicator.init(params.modelSnapshot()); + createProcessAndSetRunning(processContext, params, handler); + processContext.getAutodetectCommunicator().init(params.modelSnapshot()); setJobState(jobTask, JobState.OPENED); } catch (Exception e1) { // No need to log here as the persistent task framework will log it try { // Don't leave a partially initialised process hanging around - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.remove(jobTask.getAllocationId()); - if (communicator != null) { - communicator.killProcess(false, false); - } + processContext.newKillBuilder() + .setAwaitCompletion(false) + .setFinish(false) + .kill(); + processByAllocation.remove(jobTask.getAllocationId()); } finally { setJobState(jobTask, JobState.FAILED, e2 -> handler.accept(e1)); } @@ -333,13 +324,28 @@ public class AutodetectProcessManager extends AbstractComponent { }); } + private void createProcessAndSetRunning(ProcessContext processContext, AutodetectParams params, Consumer handler) { + try { + // At this point we lock the process context until the process has been started. + // The reason behind this is to ensure closing the job does not happen before + // the process is started as that can result to the job getting seemingly closed + // but the actual process is hanging alive. + processContext.tryLock(); + AutodetectCommunicator communicator = create(processContext.getJobTask(), params, handler); + processContext.setRunning(communicator); + } finally { + // Now that the process is running and we have updated its state we can unlock. + // It is important to unlock before we initialize the communicator (ie. load the model state) + // as that may be a long-running method. + processContext.unlock(); + } + } + AutodetectCommunicator create(JobTask jobTask, AutodetectParams autodetectParams, Consumer handler) { // Closing jobs can still be using some or all threads in MachineLearning.AUTODETECT_THREAD_POOL_NAME // that an open job uses, so include them too when considering if enough threads are available. - // There's a slight possibility that the same key is in both sets, hence it's not sufficient to simply - // add the two map sizes. - int currentRunningJobs = Sets.union(autoDetectCommunicatorByOpenJob.keySet(), autoDetectCommunicatorByClosingJob.keySet()).size(); - if (currentRunningJobs >= maxAllowedRunningJobs) { + int currentRunningJobs = processByAllocation.size(); + if (currentRunningJobs > maxAllowedRunningJobs) { throw new ElasticsearchStatusException("max running job capacity [" + maxAllowedRunningJobs + "] reached", RestStatus.TOO_MANY_REQUESTS); } @@ -390,7 +396,7 @@ public class AutodetectProcessManager extends AbstractComponent { } throw e; } - return new AutodetectCommunicator(job, jobTask, process, new StateStreamer(client), dataCountsReporter, processor, handler, + return new AutodetectCommunicator(job, process, new StateStreamer(client), dataCountsReporter, processor, handler, xContentRegistry, autodetectWorkerExecutor); } @@ -429,31 +435,34 @@ public class AutodetectProcessManager extends AbstractComponent { String jobId = jobTask.getJobId(); long allocationId = jobTask.getAllocationId(); logger.debug("Attempting to close job [{}], because [{}]", jobId, reason); - // don't remove the communicator immediately, because we need to ensure it's in the - // map of closing communicators before it's removed from the map of running ones - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(allocationId); - if (communicator == null) { - logger.debug("Cannot close: no active autodetect process for job [{}]", jobId); - return; - } - // keep a record of the job, so that it can still be killed while closing - autoDetectCommunicatorByClosingJob.putIfAbsent(allocationId, communicator); - communicator = autoDetectCommunicatorByOpenJob.remove(allocationId); - if (communicator == null) { - // if we get here a simultaneous close request beat us to the remove() call - logger.debug("Already closing autodetect process for job [{}]", jobId); + // don't remove the process context immediately, because we need to ensure + // it is reachable to enable killing a job while it is closing + ProcessContext processContext = processByAllocation.get(allocationId); + if (processContext == null) { + logger.debug("Cannot close job [{}] as it has already been closed", jobId); return; } + processContext.tryLock(); + processContext.setDying(); + processContext.unlock(); + if (reason == null) { logger.info("Closing job [{}]", jobId); } else { logger.info("Closing job [{}], because [{}]", jobId, reason); } + AutodetectCommunicator communicator = processContext.getAutodetectCommunicator(); + if (communicator == null) { + logger.debug("Job [{}] is being closed before its process is started", jobId); + jobTask.markAsCompleted(); + return; + } + try { communicator.close(restart, reason); - autoDetectCommunicatorByClosingJob.remove(allocationId); + processByAllocation.remove(allocationId); } catch (Exception e) { logger.warn("[" + jobId + "] Exception closing autodetect process", e); setJobState(jobTask, JobState.FAILED); @@ -462,15 +471,29 @@ public class AutodetectProcessManager extends AbstractComponent { } int numberOfOpenJobs() { - return autoDetectCommunicatorByOpenJob.size(); + return (int) processByAllocation.values().stream() + .filter(p -> p.getState() != ProcessContext.ProcessStateName.DYING) + .count(); } boolean jobHasActiveAutodetectProcess(JobTask jobTask) { - return autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()) != null; + return getAutodetectCommunicator(jobTask) != null; + } + + private AutodetectCommunicator getAutodetectCommunicator(JobTask jobTask) { + return processByAllocation.getOrDefault(jobTask.getAllocationId(), new ProcessContext(jobTask)).getAutodetectCommunicator(); + } + + private AutodetectCommunicator getOpenAutodetectCommunicator(JobTask jobTask) { + ProcessContext processContext = processByAllocation.get(jobTask.getAllocationId()); + if (processContext.getState() == ProcessContext.ProcessStateName.RUNNING) { + return processContext.getAutodetectCommunicator(); + } + return null; } public Optional jobOpenTime(JobTask jobTask) { - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()); + AutodetectCommunicator communicator = getAutodetectCommunicator(jobTask); if (communicator == null) { return Optional.empty(); } @@ -516,7 +539,7 @@ public class AutodetectProcessManager extends AbstractComponent { } public Optional> getStatistics(JobTask jobTask) { - AutodetectCommunicator communicator = autoDetectCommunicatorByOpenJob.get(jobTask.getAllocationId()); + AutodetectCommunicator communicator = getAutodetectCommunicator(jobTask); if (communicator == null) { return Optional.empty(); } @@ -597,6 +620,5 @@ public class AutodetectProcessManager extends AbstractComponent { awaitTermination.countDown(); } } - } } diff --git a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java index 04870785e06..16ec2621c92 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java @@ -39,7 +39,7 @@ public class NativeAutodetectProcessFactory implements AutodetectProcessFactory private static final Logger LOGGER = Loggers.getLogger(NativeAutodetectProcessFactory.class); private static final NamedPipeHelper NAMED_PIPE_HELPER = new NamedPipeHelper(); - private static final Duration PROCESS_STARTUP_TIMEOUT = Duration.ofSeconds(10); + public static final Duration PROCESS_STARTUP_TIMEOUT = Duration.ofSeconds(10); private final Client client; private final Environment env; diff --git a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/ProcessContext.java b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/ProcessContext.java new file mode 100644 index 00000000000..409639705ae --- /dev/null +++ b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/ProcessContext.java @@ -0,0 +1,195 @@ +/* + * 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.ml.job.process.autodetect; + +import org.apache.logging.log4j.Logger; +import org.elasticsearch.ElasticsearchException; +import org.elasticsearch.common.logging.Loggers; +import org.elasticsearch.xpack.ml.action.OpenJobAction.JobTask; +import org.elasticsearch.xpack.ml.utils.ExceptionsHelper; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + +/** + * The process context that encapsulates the job task, the process state and the autodetect communicator. + */ +final class ProcessContext { + + private static final Logger LOGGER = Loggers.getLogger(ProcessContext.class); + + private final ReentrantLock lock = new ReentrantLock(); + private final JobTask jobTask; + private volatile AutodetectCommunicator autodetectCommunicator; + private volatile ProcessState state; + + ProcessContext(JobTask jobTask) { + this.jobTask = jobTask; + this.state = new ProcessNotRunningState(); + } + + JobTask getJobTask() { + return jobTask; + } + + AutodetectCommunicator getAutodetectCommunicator() { + return autodetectCommunicator; + } + + private void setAutodetectCommunicator(AutodetectCommunicator autodetectCommunicator) { + this.autodetectCommunicator = autodetectCommunicator; + } + + ProcessStateName getState() { + return state.getName(); + } + + private void setState(ProcessState state) { + this.state = state; + } + + void tryLock() { + try { + if (lock.tryLock(NativeAutodetectProcessFactory.PROCESS_STARTUP_TIMEOUT.getSeconds(), TimeUnit.SECONDS) == false) { + LOGGER.error("Failed to acquire process lock for job [{}]", jobTask.getJobId()); + throw ExceptionsHelper.serverError("Failed to acquire process lock for job [" + jobTask.getJobId() + "]"); + } + } catch (InterruptedException e) { + throw new ElasticsearchException(e); + } + } + + void unlock() { + lock.unlock(); + } + + void setRunning(AutodetectCommunicator autodetectCommunicator) { + assert lock.isHeldByCurrentThread(); + state.setRunning(this, autodetectCommunicator); + } + + void setDying() { + assert lock.isHeldByCurrentThread(); + state.setDying(this); + } + + KillBuilder newKillBuilder() { + return new ProcessContext.KillBuilder(); + } + + class KillBuilder { + private boolean awaitCompletion; + private boolean finish; + private boolean silent; + private String reason; + + KillBuilder setAwaitCompletion(boolean awaitCompletion) { + this.awaitCompletion = awaitCompletion; + return this; + } + + KillBuilder setFinish(boolean finish) { + this.finish = finish; + return this; + } + + KillBuilder setSilent(boolean silent) { + this.silent = silent; + return this; + } + + KillBuilder setReason(String reason) { + this.reason = reason; + return this; + } + + void kill() { + if (autodetectCommunicator == null) { + return; + } + String jobId = jobTask.getJobId(); + + if (silent == false) { + String extraInfo = (state.getName() == ProcessStateName.DYING) ? " while closing" : ""; + if (reason == null) { + LOGGER.info("Killing job [{}]{}", jobId, extraInfo); + } else { + LOGGER.info("Killing job [{}]{}, because [{}]", jobId, extraInfo, reason); + } + } + try { + autodetectCommunicator.killProcess(awaitCompletion, finish); + } catch (IOException e) { + LOGGER.error("[{}] Failed to kill autodetect process for job", jobId); + } + } + } + + enum ProcessStateName { + NOT_RUNNING, RUNNING, DYING + } + + private interface ProcessState { + void setRunning(ProcessContext processContext, AutodetectCommunicator autodetectCommunicator); + void setDying(ProcessContext processContext); + ProcessStateName getName(); + } + + private static class ProcessNotRunningState implements ProcessState { + @Override + public void setRunning(ProcessContext processContext, AutodetectCommunicator autodetectCommunicator) { + processContext.setAutodetectCommunicator(autodetectCommunicator); + processContext.setState(new ProcessRunningState()); + } + + @Override + public void setDying(ProcessContext processContext) { + processContext.setState(new ProcessDyingState()); + } + + @Override + public ProcessStateName getName() { + return ProcessStateName.NOT_RUNNING; + } + } + + private static class ProcessRunningState implements ProcessState { + + @Override + public void setRunning(ProcessContext processContext, AutodetectCommunicator autodetectCommunicator) { + LOGGER.debug("Process set to [running] while it was already in that state"); + } + + @Override + public void setDying(ProcessContext processContext) { + processContext.setState(new ProcessDyingState()); + } + + @Override + public ProcessStateName getName() { + return ProcessStateName.RUNNING; + } + } + + private static class ProcessDyingState implements ProcessState { + + @Override + public void setRunning(ProcessContext processContext, AutodetectCommunicator autodetectCommunicator) { + LOGGER.debug("Process set to [running] while it was in [dying]"); + } + + @Override + public void setDying(ProcessContext processContext) { + LOGGER.debug("Process set to [dying] while it was already in that state"); + } + + @Override + public ProcessStateName getName() { + return ProcessStateName.DYING; + } + } +} diff --git a/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicatorTests.java b/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicatorTests.java index 27396737af5..de03143be9a 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicatorTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectCommunicatorTests.java @@ -198,9 +198,7 @@ public class AutodetectCommunicatorTests extends ESTestCase { ((ActionListener) invocation.getArguments()[0]).onResponse(true); return null; }).when(dataCountsReporter).finishReporting(any()); - JobTask jobTask = mock(JobTask.class); - when(jobTask.getJobId()).thenReturn("foo"); - return new AutodetectCommunicator(createJobDetails(), jobTask, autodetectProcess, stateStreamer, + return new AutodetectCommunicator(createJobDetails(), autodetectProcess, stateStreamer, dataCountsReporter, autoDetectResultProcessor, finishHandler, new NamedXContentRegistry(Collections.emptyList()), executorService); } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManagerTests.java b/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManagerTests.java index 636f9d2e029..8e281c7034c 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManagerTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/ml/job/process/autodetect/AutodetectProcessManagerTests.java @@ -459,7 +459,6 @@ public class AutodetectProcessManagerTests extends ESTestCase { JobTask jobTask = mock(JobTask.class); when(jobTask.getJobId()).thenReturn("foo"); assertFalse(manager.jobHasActiveAutodetectProcess(jobTask)); - when(communicator.getJobTask()).thenReturn(jobTask); manager.openJob(jobTask, e -> {}); manager.processData(jobTask, createInputStream(""), randomFrom(XContentType.values()), From 5ad170a7ed6ed26d8baadec06773a78df84dea5c Mon Sep 17 00:00:00 2001 From: Dimitrios Athanasiou Date: Tue, 26 Sep 2017 12:08:15 +0100 Subject: [PATCH 7/9] Fix compilation due to upstream change Original commit: elastic/x-pack-elasticsearch@57d834841d01b869bd3f20766db1f2742003cd20 --- .../authc/esnative/ESNativeRealmMigrateToolTests.java | 4 +++- .../authc/esnative/tool/SetupPasswordToolTests.java | 8 ++++++-- .../xpack/security/crypto/tool/SystemKeyToolTests.java | 4 +++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateToolTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateToolTests.java index b7e36d2f6c6..32a9217eb44 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateToolTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/ESNativeRealmMigrateToolTests.java @@ -46,7 +46,9 @@ public class ESNativeRealmMigrateToolTests extends CommandTestCase { @Override protected Environment createEnv(Terminal terminal, Map settings) throws UserException { - return new Environment(Settings.builder().put(settings).build()); + Settings.Builder builder = Settings.builder(); + settings.forEach((k,v) -> builder.put(k, v)); + return new Environment(builder.build()); } }; diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java index 89b08eb0dc4..dcc1210a3cf 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/authc/esnative/tool/SetupPasswordToolTests.java @@ -100,7 +100,9 @@ public class SetupPasswordToolTests extends CommandTestCase { return new AutoSetup() { @Override protected Environment createEnv(Terminal terminal, Map settings) throws UserException { - return new Environment(Settings.builder().put(settings).build()); + Settings.Builder builder = Settings.builder(); + settings.forEach((k,v) -> builder.put(k, v)); + return new Environment(builder.build()); } }; } @@ -110,7 +112,9 @@ public class SetupPasswordToolTests extends CommandTestCase { return new InteractiveSetup() { @Override protected Environment createEnv(Terminal terminal, Map settings) throws UserException { - return new Environment(Settings.builder().put(settings).build()); + Settings.Builder builder = Settings.builder(); + settings.forEach((k,v) -> builder.put(k, v)); + return new Environment(builder.build()); } }; } diff --git a/plugin/src/test/java/org/elasticsearch/xpack/security/crypto/tool/SystemKeyToolTests.java b/plugin/src/test/java/org/elasticsearch/xpack/security/crypto/tool/SystemKeyToolTests.java index 8ffb5b77469..8f832e0a9e3 100644 --- a/plugin/src/test/java/org/elasticsearch/xpack/security/crypto/tool/SystemKeyToolTests.java +++ b/plugin/src/test/java/org/elasticsearch/xpack/security/crypto/tool/SystemKeyToolTests.java @@ -50,7 +50,9 @@ public class SystemKeyToolTests extends CommandTestCase { @Override protected Environment createEnv(Terminal terminal, Map settings) throws UserException { - return new Environment(Settings.builder().put(settings).build()); + Settings.Builder builder = Settings.builder(); + settings.forEach((k,v) -> builder.put(k, v)); + return new Environment(builder.build()); } }; From b3ae0229851c0567bba7f1feafd25f562de6f6e9 Mon Sep 17 00:00:00 2001 From: Dimitris Athanasiou Date: Tue, 26 Sep 2017 14:12:27 +0100 Subject: [PATCH 8/9] [ML] Remove unused member in NativeAutodetectProcessFactory (elastic/x-pack-elasticsearch#2629) Original commit: elastic/x-pack-elasticsearch@31f265f0e56c5b801081cc92055ecd4a3bc44b66 --- .../java/org/elasticsearch/xpack/ml/MachineLearning.java | 2 +- .../process/autodetect/NativeAutodetectProcessFactory.java | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/plugin/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java b/plugin/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java index 57bde0eb70c..df819ef874c 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/ml/MachineLearning.java @@ -283,7 +283,7 @@ public class MachineLearning implements ActionPlugin { // This will only only happen when path.home is not set, which is disallowed in production throw new ElasticsearchException("Failed to create native process controller for Machine Learning"); } - autodetectProcessFactory = new NativeAutodetectProcessFactory(jobProvider, env, settings, nativeController, internalClient); + autodetectProcessFactory = new NativeAutodetectProcessFactory(env, settings, nativeController, internalClient); normalizerProcessFactory = new NativeNormalizerProcessFactory(env, settings, nativeController); } catch (IOException e) { // This also should not happen in production, as the MachineLearningFeatureSet should have diff --git a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java index 16ec2621c92..02ddb82198a 100644 --- a/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java +++ b/plugin/src/main/java/org/elasticsearch/xpack/ml/job/process/autodetect/NativeAutodetectProcessFactory.java @@ -14,7 +14,6 @@ import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException; import org.elasticsearch.env.Environment; import org.elasticsearch.xpack.ml.job.config.Job; import org.elasticsearch.xpack.ml.job.config.MlFilter; -import org.elasticsearch.xpack.ml.job.persistence.JobProvider; import org.elasticsearch.xpack.ml.job.process.NativeController; import org.elasticsearch.xpack.ml.job.process.ProcessCtrl; import org.elasticsearch.xpack.ml.job.process.ProcessPipes; @@ -44,14 +43,11 @@ public class NativeAutodetectProcessFactory implements AutodetectProcessFactory private final Client client; private final Environment env; private final Settings settings; - private final JobProvider jobProvider; private final NativeController nativeController; - public NativeAutodetectProcessFactory(JobProvider jobProvider, Environment env, Settings settings, - NativeController nativeController, Client client) { + public NativeAutodetectProcessFactory(Environment env, Settings settings, NativeController nativeController, Client client) { this.env = Objects.requireNonNull(env); this.settings = Objects.requireNonNull(settings); - this.jobProvider = Objects.requireNonNull(jobProvider); this.nativeController = Objects.requireNonNull(nativeController); this.client = client; } From 64e2f4c93c8c3703b7404945f788f28d0a19f36b Mon Sep 17 00:00:00 2001 From: Lisa Cawley Date: Tue, 26 Sep 2017 08:52:04 -0700 Subject: [PATCH 9/9] Update bootstrap security details (elastic/x-pack-elasticsearch#2430) * [DOCS] Update bootstrap security details * [DOCS] Addressed feedback about bootstrap * [DOCS] Update bootstrap password details * [DOCS] Addressed feedback about setup-passwords * [DOCS] Update security in x-pack install info * [DOCS] Remove bootstrap.password details * [DOCS] Update setup-passwords info * [DOCS] Re-add bootstrap.password details Original commit: elastic/x-pack-elasticsearch@04d3ee850948f40bc85a377132257980911ef021 --- docs/en/commands/index.asciidoc | 3 +- docs/en/commands/setup-passwords.asciidoc | 47 ++++++++ docs/en/installing-xes.asciidoc | 22 ++-- docs/en/security/authentication.asciidoc | 136 +++++++++++----------- docs/en/security/getting-started.asciidoc | 30 ++--- 5 files changed, 145 insertions(+), 93 deletions(-) create mode 100644 docs/en/commands/setup-passwords.asciidoc diff --git a/docs/en/commands/index.asciidoc b/docs/en/commands/index.asciidoc index 12792f74ec7..69f279f90ff 100644 --- a/docs/en/commands/index.asciidoc +++ b/docs/en/commands/index.asciidoc @@ -8,10 +8,11 @@ {xpack} includes commands that help you configure security: * <> -//* <> +* <> * <> -- include::certgen.asciidoc[] +include::setup-passwords.asciidoc[] include::users-command.asciidoc[] diff --git a/docs/en/commands/setup-passwords.asciidoc b/docs/en/commands/setup-passwords.asciidoc new file mode 100644 index 00000000000..0b7450e2e06 --- /dev/null +++ b/docs/en/commands/setup-passwords.asciidoc @@ -0,0 +1,47 @@ +[role="xpack"] +[[setup-passwords]] +== setup-passwords + +The `setup-passwords` command sets the passwords for the built-in `elastic`, +`kibana`, and `logstash_system` users. + +[float] +=== Synopsis + +[source,shell] +-------------------------------------------------- +bin/x-pack/setup-passwords auto|interactive [-u ""] +-------------------------------------------------- + +[float] +=== Description + +This command is intended for use only during the initial configuration of +{xpack}. It uses the +{xpack-ref}/setting-up-authentication.html#bootstrap-elastic-passwords[`elastic` bootstrap password] +to run user management API requests. After you set a password for the `elastic` +user, the bootstrap password is no longer active and you cannot use this command. +Instead, you can change passwords by using the *Management > Users* UI in {kib} +or the <>. + +[float] +=== Parameters + +`auto`:: Outputs randomly-generated passwords to the console. + +`interactive`:: Prompts you to manually enter passwords. + +`-u ""`:: Specifies the URL that the tool uses to submit the user management API +requests. The default value is determined from the settings in your +`elasticsearch.yml` file. + +[float] +=== Examples + +The following example uses the `-u` parameter to tell the tool where to submit +its user management API requests: + +[source,shell] +-------------------------------------------------- +bin/x-pack/setup-passwords auto -u "http://localhost:9201" +-------------------------------------------------- diff --git a/docs/en/installing-xes.asciidoc b/docs/en/installing-xes.asciidoc index 0107c2896c3..1f837184572 100644 --- a/docs/en/installing-xes.asciidoc +++ b/docs/en/installing-xes.asciidoc @@ -197,19 +197,27 @@ bin/elasticsearch ---------------------------------------------------------- -- -.. Set the passwords for all built-in users. You can update passwords from the -**Management > Users** UI in {kib}, use the `setup-passwords` tool, or use the -security user API. For example: +.. Set the passwords for all built-in users. The +setup-passwords+ command is +the simplest method to set the built-in users' passwords for the first time. + -- +For example, you can run the command in an "interactive" mode, which prompts you +to enter new passwords for the `elastic`, `kibana`, and `logstash_system` users: + [source,shell] -------------------------------------------------- bin/x-pack/setup-passwords interactive -------------------------------------------------- -If you prefer to have randomly generated passwords, specify `auto` instead of -`interactive`. If the node is not listening on "http://localhost:9200", use the -`-u` parameter to specify the appropriate URL. For more information, -see {xpack-ref}/setting-up-authentication.html[Setting Up User Authentication]. + +For more information about the command options, see <>. + +IMPORTANT: The `setup-passwords` command uses a transient bootstrap password +that is no longer valid after the command runs successfully. You cannot run the +`setup-passwords` command a second time. Instead, you can update passwords from +the **Management > Users** UI in {kib} or use the security user API. + +For more information, see +{ref}/setting-up-authentication.html#set-built-in-user-passwords[Setting Built-in User Passwords]. -- . {kibana-ref}/installing-xpack-kb.html[Install {xpack} on {kib}]. diff --git a/docs/en/security/authentication.asciidoc b/docs/en/security/authentication.asciidoc index 3674e3951e7..7acf0acd029 100644 --- a/docs/en/security/authentication.asciidoc +++ b/docs/en/security/authentication.asciidoc @@ -19,13 +19,10 @@ These users have a fixed set of privileges and cannot be authenticated until the passwords have been set. The `elastic` user can be used to <>. -.{security} Built-in Users -|======== -| Name | Description -| `elastic` | A built-in _superuser_. See <>. -| `kibana` | The user Kibana uses to connect and communicate with Elasticsearch. -| `logstash_system` | The user Logstash uses when storing monitoring information in Elasticsearch. -|======== +`elastic`:: A built-in _superuser_. See <>. +`kibana`:: The user Kibana uses to connect and communicate with Elasticsearch. +`logstash_system`:: The user Logstash uses when storing monitoring information in Elasticsearch. + [float] [[built-in-user-explanation]] @@ -43,74 +40,84 @@ realm will not have any effect on the built-in users. The built-in users can be disabled individually, using the {ref}/security-api-users.html[user management API]. +[float] +[[bootstrap-elastic-passwords]] +==== The Elastic Bootstrap Password + +When you install {xpack}, if the `elastic` user does not already have a password, +it uses a default bootstrap password. The bootstrap password is a transient +password that enables you to run the tools that set all the built-in user passwords. + +By default, the bootstrap password is derived from a randomized `keystore.seed` +setting, which is added to the keystore when you install {xpack}. You do not need +to know or change this bootstrap password. If you have defined a +`bootstrap.password` setting in the keystore, however, that value is used instead. +For more information about interacting with the keystore, see +{ref}/secure-settings.html[Secure Settings]. +//// +//TBD: Is the following still true? +As the `elastic` user is stored in the native realm, the password will be +synced to all the nodes in a cluster. It is safe to bootstrap the password with +multiple nodes as long as the password is the same. If different passwords are +set with different nodes, it is unpredictable which password will be bootstrapped. +//// + +NOTE: After you <>, +in particular for the `elastic` user, there is no further use for the bootstrap +password. + [float] [[set-built-in-user-passwords]] -==== Set Built-in User Passwords -[IMPORTANT] -============================================================================= +==== Setting Built-in User Passwords + You must set the passwords for all built-in users. -You can update passwords from the *Management > Users* UI in Kibana, using the -setup-passwords tool, or with the security user api. -The setup-passwords tool is a command line tool that is provided to assist with -setup. When it is run, it will use the `elastic` user to execute API requests -that will change the passwords of the `elastic`, `kibana`, and -`logstash_system` users. In "auto" mode the passwords will be generated randomly and -printed to the console. - -[source,shell] --------------------------------------------------- -bin/x-pack/setup-passwords auto --------------------------------------------------- - -There is also an "interactive" mode that will prompt you to manually enter passwords. +The +setup-passwords+ tool is the simplest method to set the built-in users' +passwords for the first time. It uses the `elastic` user's bootstrap password to +run user management API requests. For example, you can run the command in +an "interactive" mode, which prompts you to enter new passwords for the +`elastic`, `kibana`, and `logstash_system` users: [source,shell] -------------------------------------------------- bin/x-pack/setup-passwords interactive -------------------------------------------------- -If the node is not listening at "http://localhost:9200", you will need to pass the url parameter -to tell the tool where to submit the requests. +For more information about the command options, see +{ref}/setup-passwords.html[setup-passwords]. + +IMPORTANT: After you set a password for the `elastic` user, the bootstrap +password is no longer valid; you cannot run the `setup-passwords` command a +second time. + +Alternatively, you can set the initial passwords for the built-in users by using +the *Management > Users* page in {kib} or the +{ref}/security-api-change-password.html[Change Password API]. These methods are +more complex. You must supply the `elastic` user and its bootstrap password to +log into {kib} or run the API. This requirement means that you cannot use the +default bootstrap password that is derived from the `keystore.seed` setting. +Instead, you must explicitly set a `bootstrap.password` setting in the keystore +before you start {es}. For example, the following command prompts you to enter a +new bootstrap password: [source,shell] --------------------------------------------------- -bin/x-pack/setup-passwords auto -u "http://localhost:9201" --------------------------------------------------- +---------------------------------------------------- +bin/elasticsearch-keystore add "bootstrap.password" +---------------------------------------------------- -The {ref}/security-api-users.html#security-api-reset-user-password[Reset Password API] can -also be used to change the passwords manually. +You can then start {es} and {kib} and use the `elastic` user and bootstrap +password to log into {kib} and change the passwords. Alternatively, you can +submit Change Password API requests for each built-in user. These methods are +better suited for changing your passwords after the initial setup is complete, +since at that point the bootstrap password is no longer required. -[source,js] ---------------------------------------------------------------------- -PUT _xpack/security/user/elastic/_password -{ - "password": "elasticpassword" -} ---------------------------------------------------------------------- -// CONSOLE +[float] +[[add-built-in-user-passwords]] +==== Adding Built-in User Passwords To {kib} and Logstash -[source,js] ---------------------------------------------------------------------- -PUT _xpack/security/user/kibana/_password -{ - "password": "kibanapassword" -} ---------------------------------------------------------------------- -// CONSOLE - -[source,js] ---------------------------------------------------------------------- -PUT _xpack/security/user/logstash_system/_password -{ - "password": "logstashpassword" -} ---------------------------------------------------------------------- -// CONSOLE - -Once the `kibana` user password is reset, you need to update the Kibana server -with the new password by setting `elasticsearch.password` in the -`kibana.yml` configuration file: +After the `kibana` user password is set, you need to update the {kib} server +with the new password by setting `elasticsearch.password` in the `kibana.yml` +configuration file: [source,yaml] ----------------------------------------------- @@ -138,16 +145,15 @@ Once the password has been changed, you can enable the user via the following AP PUT _xpack/security/user/logstash_system/_enable --------------------------------------------------------------------- // CONSOLE -============================================================================= [float] [[disabling-default-password]] -==== Disable Default Password Functionality +==== Disabling Default Password Functionality [IMPORTANT] ============================================================================= -This setting is deprecated. The elastic user no longer has a default password. The password must -be set before the user can be used. - +This setting is deprecated. The elastic user no longer has a default password. +The password must be set before the user can be used. +See <>. ============================================================================= [float] diff --git a/docs/en/security/getting-started.asciidoc b/docs/en/security/getting-started.asciidoc index 1375008b682..75d22d2e90a 100644 --- a/docs/en/security/getting-started.asciidoc +++ b/docs/en/security/getting-started.asciidoc @@ -16,23 +16,12 @@ To get started with {security}: . <>. -. On at least one of the nodes in your cluster, set the "bootstrap.password" secure setting in the keystore. -+ --- -[source,shell] --------------------------------------------------- -bin/elasticsearch-keystore create -bin/elasticsearch-keystore add "bootstrap.password" --------------------------------------------------- +. Start {es} and {kib}. --- - -. Start Elasticsearch and Kibana. The Elasticsearch node with the "bootstrap.password" setting will use that -setting to set the `elastic` user password on node startup. - - -. Set the passwords of the built in `elastic`, `kibana`, and `logstash_system` users using the provided setup -passwords tool. In "auto" mode this tool will randomly generate passwords and print them to the console. +. Set the passwords of the built in `elastic`, `kibana`, and `logstash_system` users. +In most cases, you can simply run the `bin/x-pack/setup-passwords` tool on one of the nodes in your cluster. +Run that command with the same user that is running your {es} process. +In "auto" mode this tool will randomly generate passwords and print them to the console. + -- [source,shell] @@ -40,9 +29,10 @@ passwords tool. In "auto" mode this tool will randomly generate passwords and pr bin/x-pack/setup-passwords auto -------------------------------------------------- +For more information, see <>. -- -. Set up roles and users to control access to Elasticsearch and Kibana. +. Set up roles and users to control access to {es} and {kib}. For example, to grant _John Doe_ full access to all indices that match the pattern `events*` and enable him to create visualizations and dashboards for those indices in Kibana, you could create an `events_admin` role and @@ -76,7 +66,7 @@ curl -XPOST -u elastic 'localhost:9200/_xpack/security/user/johndoe' -H "Content [[enable-auditing]] . Enable Auditing to keep track of attempted and successful interactions with - your Elasticsearch cluster: + your {es} cluster: + -- .. Add the following setting to `elasticsearch.yml` on all nodes in your cluster: @@ -85,10 +75,10 @@ curl -XPOST -u elastic 'localhost:9200/_xpack/security/user/johndoe' -H "Content ---------------------------- xpack.security.audit.enabled: true ---------------------------- -.. Restart Elasticsearch. +.. Restart {es}. By default, events are logged to a dedicated `elasticsearch-access.log` file in -`ES_HOME/logs`. You can also store the events in an Elasticsearch index for +`ES_HOME/logs`. You can also store the events in an {es} index for easier analysis and control what events are logged. For more information, see {xpack-ref}/auditing.html[Configuring Auditing]. --