From 8493c2b1bb1921573bd5a4a84d34b7b8c24d52da Mon Sep 17 00:00:00 2001 From: Michal Duda Date: Tue, 27 Oct 2020 23:02:20 +0100 Subject: [PATCH] SONAR-13979 Fail when sonar.search.host or sonar.search.port are defined in DCE - Orchestrator upgrade was required as by default it was setting these properties --- build.gradle | 2 +- .../application/config/ClusterSettings.java | 16 + .../org/sonar/application/es/EsSettings.java | 25 +- .../application/AppReloaderImplTest.java | 24 +- .../application/AppStateFactoryTest.java | 23 +- .../sonar/application/SchedulerImplTest.java | 112 ++++--- .../StopRequestWatcherImplTest.java | 11 +- .../AppNodesClusterHostsConsistencyTest.java | 14 +- .../config/ClusterSettingsLoopbackTest.java | 48 +-- .../config/ClusterSettingsTest.java | 308 ++++++++++-------- .../application/config/TestAppSettings.java | 15 +- .../org/sonar/process/ProcessProperties.java | 18 +- .../sonar/process/ProcessPropertiesTest.java | 41 ++- 13 files changed, 385 insertions(+), 272 deletions(-) diff --git a/build.gradle b/build.gradle index a7e1f05d425..5cf8dd96848 100644 --- a/build.gradle +++ b/build.gradle @@ -368,7 +368,7 @@ subprojects { dependency 'org.postgresql:postgresql:42.2.17' dependency 'org.reflections:reflections:0.9.12' dependency 'org.simpleframework:simple:4.1.21' - dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.31.0.2646' + dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.32.0.2670' dependency 'org.sonarsource.update-center:sonar-update-center-common:1.23.0.723' dependency 'org.subethamail:subethasmtp:3.1.7' dependency 'org.yaml:snakeyaml:1.26' diff --git a/server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java b/server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java index 7b059868940..504f6885483 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java +++ b/server/sonar-main/src/main/java/org/sonar/application/config/ClusterSettings.java @@ -21,6 +21,7 @@ package org.sonar.application.config; import com.google.common.net.HostAndPort; import java.util.Arrays; +import java.util.EnumSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -54,8 +55,11 @@ import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_TYPE; import static org.sonar.process.ProcessProperties.Property.CLUSTER_SEARCH_HOSTS; import static org.sonar.process.ProcessProperties.Property.CLUSTER_WEB_STARTUP_LEADER; import static org.sonar.process.ProcessProperties.Property.JDBC_URL; +import static org.sonar.process.ProcessProperties.Property.SEARCH_HOST; +import static org.sonar.process.ProcessProperties.Property.SEARCH_PORT; public class ClusterSettings implements Consumer { + private static final Set FORBIDDEN_SEARCH_NODE_SETTINGS = EnumSet.of(SEARCH_HOST, SEARCH_PORT); private final NetworkUtils network; @@ -87,6 +91,7 @@ public class ClusterSettings implements Consumer { checkClusterSearchHosts(props); break; case SEARCH: + ensureNoSearchNodeForbiddenSettings(props); AddressAndPort searchHost = parseAndCheckHost(CLUSTER_NODE_SEARCH_HOST, requireValue(props, CLUSTER_NODE_SEARCH_HOST)); ensureLocalButNotLoopbackAddress(CLUSTER_NODE_SEARCH_HOST, searchHost); AddressAndPort esHost = parseAndCheckHost(CLUSTER_NODE_ES_HOST, requireValue(props, CLUSTER_NODE_ES_HOST)); @@ -166,6 +171,17 @@ public class ClusterSettings implements Consumer { return trimmedValue; } + private static void ensureNoSearchNodeForbiddenSettings(Props props) { + List violations = FORBIDDEN_SEARCH_NODE_SETTINGS.stream() + .filter(setting -> props.value(setting.getKey()) != null) + .map(Property::getKey) + .collect(toList()); + + if (!violations.isEmpty()) { + throw new MessageException(format("Properties [%s] are not allowed when running SonarQube in cluster mode.", String.join(", ", violations))); + } + } + private static void ensureNotH2(Props props) { String jdbcUrl = props.value(JDBC_URL.getKey()); String trimmedJdbcUrl = jdbcUrl == null ? null : jdbcUrl.trim(); diff --git a/server/sonar-main/src/main/java/org/sonar/application/es/EsSettings.java b/server/sonar-main/src/main/java/org/sonar/application/es/EsSettings.java index 3993a1a43b4..ff3765e1639 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/es/EsSettings.java +++ b/server/sonar-main/src/main/java/org/sonar/application/es/EsSettings.java @@ -51,6 +51,7 @@ public class EsSettings { private static final String ES_HTTP_PORT_KEY = "http.port"; private static final String ES_TRANSPORT_HOST_KEY = "transport.host"; private static final String ES_TRANSPORT_PORT_KEY = "transport.port"; + private static final String ES_NETWORK_HOST_KEY = "network.host"; private static final Logger LOGGER = LoggerFactory.getLogger(EsSettings.class); private static final String STANDALONE_NODE_NAME = "sonarqube"; @@ -100,23 +101,25 @@ public class EsSettings { } private void configureNetwork(Map builder) { - InetAddress searchHost = resolveAddress(SEARCH_HOST); - int searchPort = Integer.parseInt(props.nonNullValue(SEARCH_PORT.getKey())); + if (!clusterEnabled) { + InetAddress searchHost = resolveAddress(SEARCH_HOST); + int searchPort = Integer.parseInt(props.nonNullValue(SEARCH_PORT.getKey())); + builder.put(ES_HTTP_HOST_KEY, searchHost.getHostAddress()); + builder.put(ES_HTTP_PORT_KEY, valueOf(searchPort)); + builder.put(ES_NETWORK_HOST_KEY, valueOf(searchHost.getHostAddress())); + + // FIXME remove definition of transport properties when Web and CE have moved to ES Rest client + int transportPort = props.valueAsInt(SEARCH_TRANSPORT_PORT.getKey(), 9002); + builder.put(ES_TRANSPORT_HOST_KEY, searchHost.getHostAddress()); + builder.put(ES_TRANSPORT_PORT_KEY, valueOf(transportPort)); + } // see https://github.com/lmenezes/elasticsearch-kopf/issues/195 builder.put("http.cors.enabled", valueOf(true)); builder.put("http.cors.allow-origin", "*"); - builder.put(ES_HTTP_HOST_KEY, searchHost.getHostAddress()); - builder.put(ES_HTTP_PORT_KEY, valueOf(searchPort)); - builder.put("network.host", valueOf(searchHost.getHostAddress())); // Elasticsearch sets the default value of TCP reuse address to true only on non-MSWindows machines, but why ? builder.put("network.tcp.reuse_address", valueOf(true)); - - // FIXME remove definition of transport properties when Web and CE have moved to ES Rest client - int transportPort = props.valueAsInt(SEARCH_TRANSPORT_PORT.getKey(), 9002); - builder.put(ES_TRANSPORT_HOST_KEY, searchHost.getHostAddress()); - builder.put(ES_TRANSPORT_PORT_KEY, valueOf(transportPort)); } private InetAddress resolveAddress(ProcessProperties.Property prop) { @@ -158,7 +161,7 @@ public class EsSettings { int nodeTransportPort = props.valueAsInt(CLUSTER_NODE_ES_PORT.getKey(), 9002); builder.put(ES_TRANSPORT_HOST_KEY, nodeTransportHost); builder.put(ES_TRANSPORT_PORT_KEY, valueOf(nodeTransportPort)); - builder.put("network.host", nodeTransportHost); + builder.put(ES_NETWORK_HOST_KEY, nodeTransportHost); String hosts = props.value(CLUSTER_ES_HOSTS.getKey(), loopbackAddress.getHostAddress()); LOGGER.info("Elasticsearch cluster enabled. Connect to hosts [{}]", hosts); diff --git a/server/sonar-main/src/test/java/org/sonar/application/AppReloaderImplTest.java b/server/sonar-main/src/test/java/org/sonar/application/AppReloaderImplTest.java index b3296b8c68b..e9ef95dd8e2 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/AppReloaderImplTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/AppReloaderImplTest.java @@ -19,6 +19,7 @@ */ package org.sonar.application; +import com.google.common.collect.ImmutableMap; import java.io.IOException; import org.junit.Rule; import org.junit.Test; @@ -45,18 +46,16 @@ public class AppReloaderImplTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - private AppSettingsLoader settingsLoader = mock(AppSettingsLoader.class); - private FileSystem fs = mock(FileSystem.class); - private AppState state = mock(AppState.class); - private AppLogging logging = mock(AppLogging.class); - private AppReloaderImpl underTest = new AppReloaderImpl(settingsLoader, fs, state, logging); + private final AppSettingsLoader settingsLoader = mock(AppSettingsLoader.class); + private final FileSystem fs = mock(FileSystem.class); + private final AppState state = mock(AppState.class); + private final AppLogging logging = mock(AppLogging.class); + private final AppReloaderImpl underTest = new AppReloaderImpl(settingsLoader, fs, state, logging); @Test public void reload_configuration_then_reset_all() throws IOException { - AppSettings settings = new TestAppSettings().set("foo", "bar"); - AppSettings newSettings = new TestAppSettings() - .set("foo", "newBar") - .set("newProp", "newVal"); + AppSettings settings = new TestAppSettings(ImmutableMap.of("foo", "bar")); + AppSettings newSettings = new TestAppSettings(ImmutableMap.of("foo", "newBar", "newProp", "newVal")); when(settingsLoader.load()).thenReturn(newSettings); underTest.reload(settings); @@ -71,7 +70,7 @@ public class AppReloaderImplTest { @Test public void throw_ISE_if_cluster_is_enabled() throws IOException { - AppSettings settings = new TestAppSettings().set(CLUSTER_ENABLED.getKey(), "true"); + AppSettings settings = new TestAppSettings(ImmutableMap.of(CLUSTER_ENABLED.getKey(), "true")); expectedException.expect(IllegalStateException.class); expectedException.expectMessage("Restart is not possible with cluster mode"); @@ -97,9 +96,8 @@ public class AppReloaderImplTest { } private void verifyFailureIfPropertyValueChanged(String propertyKey) throws IOException { - AppSettings settings = new TestAppSettings().set(propertyKey, "val1"); - AppSettings newSettings = new TestAppSettings() - .set(propertyKey, "val2"); + AppSettings settings = new TestAppSettings(ImmutableMap.of(propertyKey, "val1")); + AppSettings newSettings = new TestAppSettings(ImmutableMap.of(propertyKey, "val2")); when(settingsLoader.load()).thenReturn(newSettings); expectedException.expect(MessageException.class); diff --git a/server/sonar-main/src/test/java/org/sonar/application/AppStateFactoryTest.java b/server/sonar-main/src/test/java/org/sonar/application/AppStateFactoryTest.java index 48cbf0754e9..4d6ae3ce726 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/AppStateFactoryTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/AppStateFactoryTest.java @@ -19,6 +19,7 @@ */ package org.sonar.application; +import com.google.common.collect.ImmutableMap; import java.net.InetAddress; import java.util.Optional; import org.hamcrest.CoreMatchers; @@ -38,20 +39,19 @@ import static org.sonar.process.ProcessProperties.Property.CLUSTER_SEARCH_HOSTS; public class AppStateFactoryTest { - private TestAppSettings settings = new TestAppSettings(); - private AppStateFactory underTest = new AppStateFactory(settings); - @Test public void create_cluster_implementation_if_cluster_is_enabled() { Optional ip = NetworkUtilsImpl.INSTANCE.getLocalNonLoopbackIpv4Address(); assumeThat(ip.isPresent(), CoreMatchers.is(true)); - - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "application"); - settings.set(CLUSTER_NODE_HOST.getKey(), ip.get().getHostAddress()); - settings.set(CLUSTER_HZ_HOSTS.getKey(), ip.get().getHostAddress()); - settings.set(CLUSTER_NAME.getKey(), "foo"); - settings.set(CLUSTER_SEARCH_HOSTS.getKey(), "localhost:9002"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "application") + .put(CLUSTER_NODE_HOST.getKey(), ip.get().getHostAddress()) + .put(CLUSTER_HZ_HOSTS.getKey(), ip.get().getHostAddress()) + .put(CLUSTER_NAME.getKey(), "foo") + .put(CLUSTER_SEARCH_HOSTS.getKey(), "localhost:9002") + .build()); + AppStateFactory underTest = new AppStateFactory(settings); AppState appState = underTest.create(); assertThat(appState).isInstanceOf(ClusterAppStateImpl.class); @@ -60,6 +60,9 @@ public class AppStateFactoryTest { @Test public void cluster_implementation_is_disabled_by_default() { + TestAppSettings settings = new TestAppSettings(); + AppStateFactory underTest = new AppStateFactory(settings); + assertThat(underTest.create()).isInstanceOf(AppStateImpl.class); } } diff --git a/server/sonar-main/src/test/java/org/sonar/application/SchedulerImplTest.java b/server/sonar-main/src/test/java/org/sonar/application/SchedulerImplTest.java index cfda9aaff50..72e1d982530 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/SchedulerImplTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/SchedulerImplTest.java @@ -21,12 +21,14 @@ package org.sonar.application; import ch.qos.logback.classic.Level; import ch.qos.logback.classic.Logger; +import com.google.common.collect.ImmutableMap; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; +import java.util.Properties; import java.util.Random; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -45,11 +47,13 @@ import org.sonar.application.command.AbstractCommand; import org.sonar.application.command.CommandFactory; import org.sonar.application.command.EsScriptCommand; import org.sonar.application.command.JavaCommand; +import org.sonar.application.config.AppSettings; import org.sonar.application.config.TestAppSettings; import org.sonar.application.process.ManagedProcess; import org.sonar.process.ProcessId; import org.sonar.process.cluster.hz.HazelcastMember; +import static com.google.common.collect.ImmutableMap.of; import static java.util.Collections.synchronizedList; import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric; import static org.assertj.core.api.Assertions.assertThat; @@ -80,14 +84,14 @@ public class SchedulerImplTest { private JavaCommand webFollowerCommand; private JavaCommand ceCommand; - private AppReloader appReloader = mock(AppReloader.class); - private TestAppSettings settings = new TestAppSettings(); - private TestCommandFactory javaCommandFactory = new TestCommandFactory(); - private TestProcessLauncher processLauncher = new TestProcessLauncher(); - private TestAppState appState = new TestAppState(); - private HazelcastMember hazelcastMember = mock(HazelcastMember.class); - private TestClusterAppState clusterAppState = new TestClusterAppState(hazelcastMember); - private List orderedStops = synchronizedList(new ArrayList<>()); + private final AppReloader appReloader = mock(AppReloader.class); + // private TestAppSettings settings = new TestAppSettings(); + private final TestCommandFactory javaCommandFactory = new TestCommandFactory(); + private final TestProcessLauncher processLauncher = new TestProcessLauncher(); + private final TestAppState appState = new TestAppState(); + private final HazelcastMember hazelcastMember = mock(HazelcastMember.class); + private final TestClusterAppState clusterAppState = new TestClusterAppState(hazelcastMember); + private final List orderedStops = synchronizedList(new ArrayList<>()); @Before public void setUp() throws Exception { @@ -110,7 +114,8 @@ public class SchedulerImplTest { @Test public void start_and_stop_sequence_of_ES_WEB_CE_in_order() throws Exception { - SchedulerImpl underTest = newScheduler(false); + TestAppSettings settings = new TestAppSettings(); + SchedulerImpl underTest = newScheduler(settings, false); underTest.schedule(); // elasticsearch does not have preconditions to start @@ -127,7 +132,8 @@ public class SchedulerImplTest { @Test public void start_and_hard_stop_sequence_of_ES_WEB_CE_in_order() throws Exception { - SchedulerImpl underTest = newScheduler(false); + TestAppSettings settings = new TestAppSettings(); + SchedulerImpl underTest = newScheduler(settings, false); underTest.schedule(); playAndVerifyStartupSequence(); @@ -143,7 +149,8 @@ public class SchedulerImplTest { @Test public void all_processes_are_stopped_if_one_process_goes_down() throws Exception { - Scheduler underTest = startAll(); + TestAppSettings settings = new TestAppSettings(); + Scheduler underTest = startAll(settings); processLauncher.waitForProcess(WEB_SERVER).destroyForcibly(); @@ -158,7 +165,8 @@ public class SchedulerImplTest { @Test public void all_processes_are_stopped_if_one_process_fails_to_start() throws Exception { - SchedulerImpl underTest = newScheduler(false); + TestAppSettings settings = new TestAppSettings(); + SchedulerImpl underTest = newScheduler(settings, false); processLauncher.makeStartupFail = COMPUTE_ENGINE; underTest.schedule(); @@ -173,7 +181,8 @@ public class SchedulerImplTest { @Test public void terminate_can_be_called_multiple_times() throws Exception { - Scheduler underTest = startAll(); + TestAppSettings settings = new TestAppSettings(); + Scheduler underTest = startAll(settings); underTest.hardStop(); processLauncher.processes.values().forEach(p -> assertThat(p.isAlive()).isFalse()); @@ -184,9 +193,10 @@ public class SchedulerImplTest { @Test public void awaitTermination_blocks_until_all_processes_are_stopped() throws Exception { - Scheduler underTest = startAll(); + TestAppSettings settings = new TestAppSettings(); + Scheduler underTest = startAll(settings); - Thread awaitingTermination = new Thread(() -> underTest.awaitTermination()); + Thread awaitingTermination = new Thread(underTest::awaitTermination); awaitingTermination.start(); assertThat(awaitingTermination.isAlive()).isTrue(); @@ -198,14 +208,16 @@ public class SchedulerImplTest { @Test public void restart_stops_all_and_restarts_all_processes() throws InterruptedException, IOException { + TestAppSettings settings = new TestAppSettings(); CountDownLatch restarting = new CountDownLatch(1); - Scheduler underTest = startAll(); + Scheduler underTest = startAll(settings); Mockito.doAnswer(t -> { orderedStops.clear(); appState.reset(); processLauncher.reset(); restarting.countDown(); - return null;}) + return null; + }) .when(appReloader).reload(settings); processLauncher.waitForProcess(WEB_SERVER).askedForRestart = true; @@ -224,7 +236,8 @@ public class SchedulerImplTest { @Test public void restart_stops_all_if_new_settings_are_not_allowed() throws Exception { - Scheduler underTest = startAll(); + AppSettings settings = new TestAppSettings(); + Scheduler underTest = startAll(settings); doThrow(new IllegalStateException("reload error")).when(appReloader).reload(settings); processLauncher.waitForProcess(WEB_SERVER).askedForRestart = true; @@ -240,10 +253,12 @@ public class SchedulerImplTest { @Test public void search_node_starts_only_elasticsearch() throws Exception { - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "search"); - addRequiredNodeProperties(); - SchedulerImpl underTest = newScheduler(true); + AppSettings settings = new TestAppSettings( + addRequiredNodeProperties(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search")).build()); + + SchedulerImpl underTest = newScheduler(settings, true); underTest.schedule(); processLauncher.waitForProcessAlive(ProcessId.ELASTICSEARCH); @@ -254,13 +269,13 @@ public class SchedulerImplTest { @Test public void application_node_starts_only_web_and_ce() throws Exception { + AppSettings settings = new TestAppSettings(of(CLUSTER_ENABLED.getKey(), "true", CLUSTER_NODE_TYPE.getKey(), "application")); clusterAppState.setOperational(ProcessId.ELASTICSEARCH); - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "application"); - SchedulerImpl underTest = newScheduler(true); + + SchedulerImpl underTest = newScheduler(settings, true); underTest.schedule(); - TestManagedProcess web = processLauncher.waitForProcessAlive(WEB_SERVER).signalAsOperational(); + processLauncher.waitForProcessAlive(WEB_SERVER).signalAsOperational(); processLauncher.waitForProcessAlive(COMPUTE_ENGINE); assertThat(processLauncher.processes).hasSize(2); @@ -269,14 +284,17 @@ public class SchedulerImplTest { @Test public void search_node_starts_even_if_web_leader_is_not_yet_operational() throws Exception { + AppSettings settings = new TestAppSettings( + addRequiredNodeProperties(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search")).build()); + // leader takes the lock, so underTest won't get it assertThat(clusterAppState.tryToLockWebLeader()).isTrue(); clusterAppState.setOperational(ProcessId.ELASTICSEARCH); - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "search"); - addRequiredNodeProperties(); - SchedulerImpl underTest = newScheduler(true); + + SchedulerImpl underTest = newScheduler(settings, true); underTest.schedule(); processLauncher.waitForProcessAlive(ProcessId.ELASTICSEARCH); @@ -287,16 +305,19 @@ public class SchedulerImplTest { @Test public void web_follower_starts_only_when_web_leader_is_operational() throws Exception { + AppSettings settings = new TestAppSettings( + addRequiredNodeProperties(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "application")).build()); + // leader takes the lock, so underTest won't get it assertThat(clusterAppState.tryToLockWebLeader()).isTrue(); clusterAppState.setOperational(ProcessId.ELASTICSEARCH); - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "application"); - SchedulerImpl underTest = newScheduler(true); + SchedulerImpl underTest = newScheduler(settings, true); underTest.schedule(); - assertThat(processLauncher.processes).hasSize(0); + assertThat(processLauncher.processes).isEmpty(); // leader becomes operational -> follower can start clusterAppState.setOperational(WEB_SERVER); @@ -309,9 +330,11 @@ public class SchedulerImplTest { @Test public void web_server_waits_for_remote_elasticsearch_to_be_started_if_local_es_is_disabled() throws Exception { - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "application"); - SchedulerImpl underTest = newScheduler(true); + AppSettings settings = new TestAppSettings( + addRequiredNodeProperties(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "application")).build()); + SchedulerImpl underTest = newScheduler(settings, true); underTest.schedule(); // WEB and CE wait for ES to be up @@ -352,13 +375,13 @@ public class SchedulerImplTest { processLauncher.processes.values().forEach(p -> assertThat(p.isAlive()).isTrue()); } - private SchedulerImpl newScheduler(boolean clustered) { + private SchedulerImpl newScheduler(AppSettings settings, boolean clustered) { return new SchedulerImpl(settings, appReloader, javaCommandFactory, processLauncher, clustered ? clusterAppState : appState) .setProcessWatcherDelayMs(1L); } - private Scheduler startAll() throws InterruptedException { - SchedulerImpl scheduler = newScheduler(false); + private Scheduler startAll(AppSettings settings) throws InterruptedException { + SchedulerImpl scheduler = newScheduler(settings, false); scheduler.schedule(); processLauncher.waitForProcess(ELASTICSEARCH).signalAsOperational(); processLauncher.waitForProcess(WEB_SERVER).signalAsOperational(); @@ -375,10 +398,11 @@ public class SchedulerImplTest { } } - private void addRequiredNodeProperties() { - settings.set(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(4)); - settings.set(CLUSTER_NODE_HOST.getKey(), randomAlphanumeric(4)); - settings.set(CLUSTER_NODE_HZ_PORT.getKey(), String.valueOf(1 + new Random().nextInt(999))); + private ImmutableMap.Builder addRequiredNodeProperties(ImmutableMap.Builder builder) { + builder.put(CLUSTER_NODE_NAME.getKey(), randomAlphanumeric(4)); + builder.put(CLUSTER_NODE_HOST.getKey(), randomAlphanumeric(4)); + builder.put(CLUSTER_NODE_HZ_PORT.getKey(), String.valueOf(1 + new Random().nextInt(999))); + return builder; } private class TestCommandFactory implements CommandFactory { diff --git a/server/sonar-main/src/test/java/org/sonar/application/StopRequestWatcherImplTest.java b/server/sonar-main/src/test/java/org/sonar/application/StopRequestWatcherImplTest.java index f97221ceffc..1401c6679cc 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/StopRequestWatcherImplTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/StopRequestWatcherImplTest.java @@ -29,6 +29,7 @@ import org.junit.rules.Timeout; import org.sonar.application.config.TestAppSettings; import org.sonar.process.sharedmemoryfile.ProcessCommands; +import static com.google.common.collect.ImmutableMap.of; import static org.assertj.core.api.Assertions.assertThat; import static org.awaitility.Awaitility.await; import static org.mockito.Mockito.mock; @@ -45,12 +46,12 @@ public class StopRequestWatcherImplTest { @Rule public TestRule safeguardTimeout = new DisableOnDebug(Timeout.seconds(60)); - private TestAppSettings appSettings = new TestAppSettings(); - private ProcessCommands commands = mock(ProcessCommands.class); - private Scheduler scheduler = mock(Scheduler.class); + private final ProcessCommands commands = mock(ProcessCommands.class); + private final Scheduler scheduler = mock(Scheduler.class); @Test public void startWatching_does_not_start_thread_if_stop_command_is_disabled() { + TestAppSettings appSettings = new TestAppSettings(); StopRequestWatcherImpl underTest = new StopRequestWatcherImpl(appSettings, scheduler, commands); underTest.startWatching(); @@ -59,7 +60,7 @@ public class StopRequestWatcherImplTest { @Test public void watch_stop_command_if_stop_command_is_enabled() { - appSettings.set(ENABLE_STOP_COMMAND.getKey(), "true"); + TestAppSettings appSettings = new TestAppSettings(of(ENABLE_STOP_COMMAND.getKey(), "true")); StopRequestWatcherImpl underTest = new StopRequestWatcherImpl(appSettings, scheduler, commands); underTest.startWatching(); @@ -77,6 +78,7 @@ public class StopRequestWatcherImplTest { @Test public void create_instance_with_default_delay() throws IOException { + TestAppSettings appSettings = new TestAppSettings(); FileSystem fs = mock(FileSystem.class); when(fs.getTempDir()).thenReturn(temp.newFolder()); @@ -87,6 +89,7 @@ public class StopRequestWatcherImplTest { @Test public void stop_watching_commands_if_thread_is_interrupted() { + TestAppSettings appSettings = new TestAppSettings(); StopRequestWatcherImpl underTest = new StopRequestWatcherImpl(appSettings, scheduler, commands); underTest.startWatching(); diff --git a/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java b/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java index d963e121d56..30b02ba317b 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/cluster/AppNodesClusterHostsConsistencyTest.java @@ -19,6 +19,7 @@ */ package org.sonar.application.cluster; +import com.google.common.collect.ImmutableMap; import com.hazelcast.core.Cluster; import com.hazelcast.core.IAtomicReference; import com.hazelcast.core.Member; @@ -48,7 +49,6 @@ import org.sonar.process.cluster.hz.HazelcastMember; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; import static org.sonar.process.ProcessProperties.Property.CLUSTER_HZ_HOSTS; @@ -56,8 +56,8 @@ public class AppNodesClusterHostsConsistencyTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - private TestAppSettings settings = new TestAppSettings(); - private Consumer logger = mock(Consumer.class); + @SuppressWarnings("unchecked") + private final Consumer logger = mock(Consumer.class); @Before @After @@ -75,7 +75,7 @@ public class AppNodesClusterHostsConsistencyTest { hostsPerMember.put(m2, Arrays.asList("1.1.1.1:1000", "1.1.1.1:2000")); hostsPerMember.put(m3, Arrays.asList("1.1.1.1:1000", "1.1.1.2:1000")); - settings.set(CLUSTER_HZ_HOSTS.getKey(), "1.1.1.1:1000,1.1.1.1:2000,1.1.1.2:1000"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.of(CLUSTER_HZ_HOSTS.getKey(), "1.1.1.1:1000,1.1.1.1:2000,1.1.1.2:1000")); TestHazelcastMember member = new TestHazelcastMember(hostsPerMember, m1); AppNodesClusterHostsConsistency underTest = AppNodesClusterHostsConsistency.setInstance(member, settings, logger); @@ -99,19 +99,19 @@ public class AppNodesClusterHostsConsistencyTest { hostsPerMember.put(m2, Arrays.asList("1.1.1.1:1000", "1.1.1.1:2000", "1.1.1.2:1000")); hostsPerMember.put(m3, Arrays.asList("1.1.1.1:1000", "1.1.1.1:2000", "1.1.1.2:1000")); - settings.set(CLUSTER_HZ_HOSTS.getKey(), "1.1.1.1:1000,1.1.1.1:2000,1.1.1.2:1000"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.of(CLUSTER_HZ_HOSTS.getKey(), "1.1.1.1:1000,1.1.1.1:2000,1.1.1.2:1000")); TestHazelcastMember member = new TestHazelcastMember(hostsPerMember, m1); AppNodesClusterHostsConsistency underTest = AppNodesClusterHostsConsistency.setInstance(member, settings, logger); underTest.check(); - verifyZeroInteractions(logger); + verifyNoMoreInteractions(logger); } @Test public void setInstance_fails_with_ISE_when_called_twice_with_same_arguments() throws UnknownHostException { TestHazelcastMember member = new TestHazelcastMember(Collections.emptyMap(), newLocalHostMember(1, true)); - + TestAppSettings settings = new TestAppSettings(); AppNodesClusterHostsConsistency.setInstance(member, settings); expectedException.expect(IllegalStateException.class); diff --git a/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java b/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java index 576dd5890b4..df6c7c092d6 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsLoopbackTest.java @@ -19,7 +19,10 @@ */ package org.sonar.application.config; +import com.google.common.collect.ImmutableMap; import java.net.InetAddress; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import org.hamcrest.CoreMatchers; import org.junit.Before; @@ -59,8 +62,7 @@ public class ClusterSettingsLoopbackTest { @Test public void ClusterSettings_throws_MessageException_if_es_http_host_of_search_node_is_loopback() { - TestAppSettings settings = newSettingsForSearchNode(); - settings.set(CLUSTER_NODE_SEARCH_HOST.getKey(), loopback.getHostAddress()); + TestAppSettings settings = newSettingsForSearchNode(ImmutableMap.of(CLUSTER_NODE_SEARCH_HOST.getKey(), loopback.getHostAddress())); Props props = settings.getProps(); ClusterSettings clusterSettings = new ClusterSettings(network); @@ -71,8 +73,7 @@ public class ClusterSettingsLoopbackTest { @Test public void ClusterSettings_throws_MessageException_if_es_transport_host_of_search_node_is_loopback() { - TestAppSettings settings = newSettingsForSearchNode(); - settings.set(CLUSTER_NODE_ES_HOST.getKey(), loopback.getHostAddress()); + TestAppSettings settings = newSettingsForSearchNode(ImmutableMap.of(CLUSTER_NODE_ES_HOST.getKey(), loopback.getHostAddress())); Props props = settings.getProps(); ClusterSettings clusterSettings = new ClusterSettings(network); @@ -83,8 +84,7 @@ public class ClusterSettingsLoopbackTest { @Test public void ClusterSettings_throws_MessageException_if_host_of_app_node_is_loopback() { - TestAppSettings settings = newSettingsForAppNode(); - settings.set(CLUSTER_NODE_HOST.getKey(), loopback.getHostAddress()); + TestAppSettings settings = newSettingsForAppNode(ImmutableMap.of(CLUSTER_NODE_HOST.getKey(), loopback.getHostAddress())); Props props = settings.getProps(); ClusterSettings clusterSettings = new ClusterSettings(network); @@ -93,23 +93,27 @@ public class ClusterSettingsLoopbackTest { .hasMessage("Property " + CLUSTER_NODE_HOST.getKey() + " must be a local non-loopback address: " + loopback.getHostAddress()); } - private TestAppSettings newSettingsForAppNode() { - return new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "application") - .set(CLUSTER_NODE_HOST.getKey(), nonLoopbackLocal.getHostAddress()) - .set(CLUSTER_HZ_HOSTS.getKey(), nonLoopbackLocal.getHostAddress()) - .set(CLUSTER_SEARCH_HOSTS.getKey(), nonLoopbackLocal.getHostAddress()) - .set("sonar.auth.jwtBase64Hs256Secret", "abcde") - .set(JDBC_URL.getKey(), "jdbc:postgresql://localhost:3306/sonar"); + private TestAppSettings newSettingsForAppNode(ImmutableMap settings) { + Map result = new HashMap<>(); + result.put(CLUSTER_ENABLED.getKey(), "true"); + result.put(CLUSTER_NODE_TYPE.getKey(), "application"); + result.put(CLUSTER_NODE_HOST.getKey(), nonLoopbackLocal.getHostAddress()); + result.put(CLUSTER_HZ_HOSTS.getKey(), nonLoopbackLocal.getHostAddress()); + result.put(CLUSTER_SEARCH_HOSTS.getKey(), nonLoopbackLocal.getHostAddress()); + result.put("sonar.auth.jwtBase64Hs256Secret", "abcde"); + result.put(JDBC_URL.getKey(), "jdbc:postgresql://localhost:3306/sonar"); + result.putAll(settings); + return new TestAppSettings(result); } - private TestAppSettings newSettingsForSearchNode() { - return new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_ES_HOSTS.getKey(), nonLoopbackLocal.getHostAddress()) - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), nonLoopbackLocal.getHostAddress()) - .set(CLUSTER_NODE_ES_HOST.getKey(), nonLoopbackLocal.getHostAddress()); + private TestAppSettings newSettingsForSearchNode(ImmutableMap settings) { + Map result = new HashMap<>(); + result.put(CLUSTER_ENABLED.getKey(), "true"); + result.put(CLUSTER_NODE_TYPE.getKey(), "search"); + result.put(CLUSTER_ES_HOSTS.getKey(), nonLoopbackLocal.getHostAddress()); + result.put(CLUSTER_NODE_SEARCH_HOST.getKey(), nonLoopbackLocal.getHostAddress()); + result.put(CLUSTER_NODE_ES_HOST.getKey(), nonLoopbackLocal.getHostAddress()); + result.putAll(settings); + return new TestAppSettings(result); } } diff --git a/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsTest.java b/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsTest.java index 73ee1b0ace4..fa8fae1a190 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/config/ClusterSettingsTest.java @@ -19,12 +19,16 @@ */ package org.sonar.application.config; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.tngtech.java.junit.dataprovider.DataProvider; import com.tngtech.java.junit.dataprovider.DataProviderRunner; import com.tngtech.java.junit.dataprovider.UseDataProvider; import java.net.InetAddress; import java.util.Arrays; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.Optional; import java.util.stream.Stream; import org.junit.Test; @@ -35,7 +39,7 @@ import org.sonar.process.MessageException; import org.sonar.process.NetworkUtils; import org.sonar.process.Props; -import static com.google.common.collect.ImmutableList.of; +import static com.google.common.collect.ImmutableMap.of; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; @@ -64,10 +68,10 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void test_isClusterEnabled(String host) { - TestAppSettings settings = newSettingsForAppNode(host).set(CLUSTER_ENABLED.getKey(), "true"); + TestAppSettings settings = newSettingsForAppNode(host, of(CLUSTER_ENABLED.getKey(), "true")); assertThat(ClusterSettings.isClusterEnabled(settings)).isTrue(); - settings = new TestAppSettings().set(CLUSTER_ENABLED.getKey(), "false"); + settings = new TestAppSettings(of(CLUSTER_ENABLED.getKey(), "false")); assertThat(ClusterSettings.isClusterEnabled(settings)).isFalse(); } @@ -78,7 +82,7 @@ public class ClusterSettingsTest { @Test public void getEnabledProcesses_returns_all_processes_in_standalone_mode() { - TestAppSettings settings = new TestAppSettings().set(CLUSTER_ENABLED.getKey(), "false"); + TestAppSettings settings = new TestAppSettings(of(CLUSTER_ENABLED.getKey(), "false")); assertThat(ClusterSettings.getEnabledProcesses(settings)).containsOnly(COMPUTE_ENGINE, ELASTICSEARCH, WEB_SERVER); } @@ -94,8 +98,7 @@ public class ClusterSettingsTest { @Test public void accept_throws_MessageException_if_no_node_type_is_configured() { - TestAppSettings settings = new TestAppSettings(); - settings.set(CLUSTER_ENABLED.getKey(), "true"); + TestAppSettings settings = new TestAppSettings(of(CLUSTER_ENABLED.getKey(), "true")); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -106,9 +109,7 @@ public class ClusterSettingsTest { @Test public void accept_throws_MessageException_if_node_type_is_not_correct() { - TestAppSettings settings = new TestAppSettings(); - settings.set(CLUSTER_ENABLED.getKey(), "true"); - settings.set(CLUSTER_NODE_TYPE.getKey(), "bla"); + TestAppSettings settings = new TestAppSettings(of(CLUSTER_ENABLED.getKey(), "true", CLUSTER_NODE_TYPE.getKey(), "bla")); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -120,8 +121,7 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void accept_throws_MessageException_if_internal_property_for_startup_leader_is_configured(String host) { - TestAppSettings settings = newSettingsForAppNode(host); - settings.set("sonar.cluster.web.startupLeader", "true"); + TestAppSettings settings = newSettingsForAppNode(host, of("sonar.cluster.web.startupLeader", "true")); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -132,19 +132,31 @@ public class ClusterSettingsTest { @Test public void accept_does_nothing_if_cluster_is_disabled() { - TestAppSettings settings = new TestAppSettings(); - settings.set(CLUSTER_ENABLED.getKey(), "false"); - // this property is supposed to fail if cluster is enabled - settings.set("sonar.cluster.web.startupLeader", "true"); - + TestAppSettings settings = new TestAppSettings(of( + CLUSTER_ENABLED.getKey(), "false", + // this property is supposed to fail if cluster is enabled + "sonar.cluster.web.startupLeader", "true")); new ClusterSettings(network).accept(settings.getProps()); } + @Test + public void accept_throws_MessageException_if_a_cluster_forbidden_property_is_defined_in_a_cluster_search_node() { + TestAppSettings settings = new TestAppSettings(of( + CLUSTER_ENABLED.getKey(), "true", + CLUSTER_NODE_TYPE.getKey(), "search", + "sonar.search.host", "localhost")); + Props props = settings.getProps(); + ClusterSettings clusterSettings = new ClusterSettings(network); + + assertThatThrownBy(() -> clusterSettings.accept(props)) + .isInstanceOf(MessageException.class) + .hasMessage("Properties [sonar.search.host] are not allowed when running SonarQube in cluster mode."); + } + @Test @UseDataProvider("validIPv4andIPv6Addresses") public void accept_throws_MessageException_if_h2_on_application_node(String host) { - TestAppSettings settings = newSettingsForAppNode(host); - settings.set("sonar.jdbc.url", "jdbc:h2:mem"); + TestAppSettings settings = newSettingsForAppNode(host, of("sonar.jdbc.url", "jdbc:h2:mem")); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -158,8 +170,7 @@ public class ClusterSettingsTest { public void accept_does_not_verify_h2_on_search_node(String host) { mockValidHost(host); mockLocalNonLoopback(host); - TestAppSettings settings = newSettingsForSearchNode(host); - settings.set("sonar.jdbc.url", "jdbc:h2:mem"); + TestAppSettings settings = newSettingsForSearchNode(host, of("sonar.jdbc.url", "jdbc:h2:mem")); // do not fail new ClusterSettings(network).accept(settings.getProps()); @@ -211,12 +222,10 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void shouldStartHazelcast_must_be_false_when_cluster_not_activated(String host) { - TestAppSettings settings = newSettingsForSearchNode(host); - settings.set(CLUSTER_ENABLED.getKey(), "false"); + TestAppSettings settings = newSettingsForSearchNode(host, of(CLUSTER_ENABLED.getKey(), "false")); assertThat(ClusterSettings.shouldStartHazelcast(settings)).isFalse(); - settings = newSettingsForAppNode(host); - settings.set(CLUSTER_ENABLED.getKey(), "false"); + settings = newSettingsForAppNode(host, of(CLUSTER_ENABLED.getKey(), "false")); assertThat(ClusterSettings.shouldStartHazelcast(settings)).isFalse(); } @@ -231,11 +240,10 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void accept_throws_MessageException_if_clusterNodeEsHost_is_missing(String host) { - TestAppSettings settings = newSettingsForSearchNode(host); String searchHost = "search_host"; + TestAppSettings settings = newSettingsForSearchNode(host, of(CLUSTER_NODE_SEARCH_HOST.getKey(), searchHost)); mockValidHost(searchHost); mockLocalNonLoopback(searchHost); - settings.set(CLUSTER_NODE_SEARCH_HOST.getKey(), searchHost); settings.clearProperty(CLUSTER_NODE_ES_HOST.getKey()); assertThatPropertyIsMandatory(settings, CLUSTER_NODE_ES_HOST.getKey()); @@ -244,11 +252,10 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void accept_throws_MessageException_if_clusterNodeSearchHost_is_missing(String host) { - TestAppSettings settings = newSettingsForSearchNode(host); String esHost = "es_host"; + TestAppSettings settings = newSettingsForSearchNode(host, of(CLUSTER_NODE_ES_HOST.getKey(), esHost)); mockValidHost(esHost); mockLocalNonLoopback(esHost); - settings.set(CLUSTER_NODE_ES_HOST.getKey(), esHost); settings.clearProperty(CLUSTER_NODE_SEARCH_HOST.getKey()); assertThatPropertyIsMandatory(settings, CLUSTER_NODE_SEARCH_HOST.getKey()); @@ -257,12 +264,12 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void accept_throws_MessageException_if_sonarClusterNodeSearchHost_is_empty(String host) { - TestAppSettings settings = newSettingsForSearchNode(host); - settings.set(CLUSTER_NODE_SEARCH_HOST.getKey(), ""); String esHost = "es_host"; + TestAppSettings settings = newSettingsForSearchNode(host, of( + CLUSTER_NODE_SEARCH_HOST.getKey(), "", + CLUSTER_NODE_ES_HOST.getKey(), esHost)); mockValidHost(esHost); mockLocalNonLoopback(esHost); - settings.set(CLUSTER_NODE_ES_HOST.getKey(), esHost); assertThatPropertyIsMandatory(settings, CLUSTER_NODE_SEARCH_HOST.getKey()); } @@ -270,12 +277,12 @@ public class ClusterSettingsTest { @Test @UseDataProvider("validIPv4andIPv6Addresses") public void accept_throws_MessageException_if_sonarClusterNodeEsHost_is_empty(String host) { - TestAppSettings settings = newSettingsForSearchNode(host); - settings.set(CLUSTER_NODE_ES_HOST.getKey(), ""); String searchHost = "search_host"; + TestAppSettings settings = newSettingsForSearchNode(host, of( + CLUSTER_NODE_ES_HOST.getKey(), "", + CLUSTER_NODE_SEARCH_HOST.getKey(), searchHost)); mockValidHost(searchHost); mockLocalNonLoopback(searchHost); - settings.set(CLUSTER_NODE_SEARCH_HOST.getKey(), searchHost); assertThatPropertyIsMandatory(settings, CLUSTER_NODE_ES_HOST.getKey()); } @@ -303,8 +310,7 @@ public class ClusterSettingsTest { public void accept_throws_MessageException_if_clusterEsHosts_is_empty(String host) { mockValidHost(host); mockLocalNonLoopback(host); - TestAppSettings settings = newSettingsForSearchNode(host); - settings.set(CLUSTER_ES_HOSTS.getKey(), ""); + TestAppSettings settings = newSettingsForSearchNode(host, of(CLUSTER_ES_HOSTS.getKey(), "")); assertThatPropertyIsMandatory(settings, CLUSTER_ES_HOSTS.getKey()); } @@ -336,40 +342,41 @@ public class ClusterSettingsTest { @Test public void validate_host_in_any_cluster_property_of_APP_node() { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "application") - .set(CLUSTER_NODE_HOST.getKey(), "hz_host") - .set(CLUSTER_HZ_HOSTS.getKey(), "remote_hz_host_1,remote_hz_host_2") - .set(CLUSTER_SEARCH_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") - .set(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar") - .set("sonar.auth.jwtBase64Hs256Secret", "abcde"); - - verifyHostIsChecked(settings, of("hz_host"), "Address in property sonar.cluster.node.host is not a valid address: hz_host"); - verifyHostIsChecked(settings, of("remote_hz_host_1"), "Address in property sonar.cluster.hosts is not a valid address: remote_hz_host_1"); - verifyHostIsChecked(settings, of("remote_hz_host_2"), "Address in property sonar.cluster.hosts is not a valid address: remote_hz_host_2"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "application") + .put(CLUSTER_NODE_HOST.getKey(), "hz_host") + .put(CLUSTER_HZ_HOSTS.getKey(), "remote_hz_host_1,remote_hz_host_2") + .put(CLUSTER_SEARCH_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") + .put(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar") + .put("sonar.auth.jwtBase64Hs256Secret", "abcde") + .build()); + + verifyHostIsChecked(settings, ImmutableList.of("hz_host"), "Address in property sonar.cluster.node.host is not a valid address: hz_host"); + verifyHostIsChecked(settings, ImmutableList.of("remote_hz_host_1"), "Address in property sonar.cluster.hosts is not a valid address: remote_hz_host_1"); + verifyHostIsChecked(settings, ImmutableList.of("remote_hz_host_2"), "Address in property sonar.cluster.hosts is not a valid address: remote_hz_host_2"); verifyHostIsChecked(settings, - of("remote_hz_host_1", "remote_hz_host_2"), + ImmutableList.of("remote_hz_host_1", "remote_hz_host_2"), "Address in property sonar.cluster.hosts is not a valid address: remote_hz_host_1, remote_hz_host_2"); - verifyHostIsChecked(settings, of("remote_search_host_1"), "Address in property sonar.cluster.search.hosts is not a valid address: remote_search_host_1"); - verifyHostIsChecked(settings, of("remote_search_host_2"), "Address in property sonar.cluster.search.hosts is not a valid address: remote_search_host_2"); + verifyHostIsChecked(settings, ImmutableList.of("remote_search_host_1"), "Address in property sonar.cluster.search.hosts is not a valid address: remote_search_host_1"); + verifyHostIsChecked(settings, ImmutableList.of("remote_search_host_2"), "Address in property sonar.cluster.search.hosts is not a valid address: remote_search_host_2"); verifyHostIsChecked(settings, - of("remote_search_host_1", "remote_search_host_2"), + ImmutableList.of("remote_search_host_1", "remote_search_host_2"), "Address in property sonar.cluster.search.hosts is not a valid address: remote_search_host_1, remote_search_host_2"); } @Test public void validate_host_resolved_in_any_cluster_property_of_SEARCH_node() { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") - .set(CLUSTER_NODE_ES_HOST.getKey(), "search_host"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search") + .put(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") + .put(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") + .put(CLUSTER_NODE_ES_HOST.getKey(), "search_host").build()); - verifyHostIsChecked(settings, of("remote_search_host_1"), "Address in property sonar.cluster.es.hosts is not a valid address: remote_search_host_1"); - verifyHostIsChecked(settings, of("remote_search_host_2"), "Address in property sonar.cluster.es.hosts is not a valid address: remote_search_host_2"); - verifyHostIsChecked(settings, of("search_host"), "Address in property sonar.cluster.node.search.host is not a valid address: search_host"); + verifyHostIsChecked(settings, ImmutableList.of("remote_search_host_1"), "Address in property sonar.cluster.es.hosts is not a valid address: remote_search_host_1"); + verifyHostIsChecked(settings, ImmutableList.of("remote_search_host_2"), "Address in property sonar.cluster.es.hosts is not a valid address: remote_search_host_2"); + verifyHostIsChecked(settings, ImmutableList.of("search_host"), "Address in property sonar.cluster.node.search.host is not a valid address: search_host"); } private void verifyHostIsChecked(TestAppSettings settings, Collection invalidHosts, String expectedMessage) { @@ -385,43 +392,45 @@ public class ClusterSettingsTest { @Test public void ensure_no_loopback_host_in_properties_of_APP_node() { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "application") - .set(CLUSTER_NODE_HOST.getKey(), "hz_host") - .set(CLUSTER_HZ_HOSTS.getKey(), "remote_hz_host_1,remote_hz_host_2") - .set(CLUSTER_SEARCH_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") - .set(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar") - .set("sonar.auth.jwtBase64Hs256Secret", "abcde"); - - verifyLoopbackChecked(settings, of("hz_host"), "Property sonar.cluster.node.host must be a local non-loopback address: hz_host"); - verifyLoopbackChecked(settings, of("remote_search_host_1"), "Property sonar.cluster.search.hosts must not contain a loopback address: remote_search_host_1"); - verifyLoopbackChecked(settings, of("remote_search_host_2"), "Property sonar.cluster.search.hosts must not contain a loopback address: remote_search_host_2"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "application") + .put(CLUSTER_NODE_HOST.getKey(), "hz_host") + .put(CLUSTER_HZ_HOSTS.getKey(), "remote_hz_host_1,remote_hz_host_2") + .put(CLUSTER_SEARCH_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") + .put(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar") + .put("sonar.auth.jwtBase64Hs256Secret", "abcde") + .build()); + + verifyLoopbackChecked(settings, ImmutableList.of("hz_host"), "Property sonar.cluster.node.host must be a local non-loopback address: hz_host"); + verifyLoopbackChecked(settings, ImmutableList.of("remote_search_host_1"), "Property sonar.cluster.search.hosts must not contain a loopback address: remote_search_host_1"); + verifyLoopbackChecked(settings, ImmutableList.of("remote_search_host_2"), "Property sonar.cluster.search.hosts must not contain a loopback address: remote_search_host_2"); verifyLoopbackChecked(settings, - of("remote_search_host_1", "remote_search_host_2"), + ImmutableList.of("remote_search_host_1", "remote_search_host_2"), "Property sonar.cluster.search.hosts must not contain a loopback address: remote_search_host_1, remote_search_host_2"); - verifyLoopbackChecked(settings, of("remote_hz_host_1"), "Property sonar.cluster.hosts must not contain a loopback address: remote_hz_host_1"); - verifyLoopbackChecked(settings, of("remote_hz_host_2"), "Property sonar.cluster.hosts must not contain a loopback address: remote_hz_host_2"); + verifyLoopbackChecked(settings, ImmutableList.of("remote_hz_host_1"), "Property sonar.cluster.hosts must not contain a loopback address: remote_hz_host_1"); + verifyLoopbackChecked(settings, ImmutableList.of("remote_hz_host_2"), "Property sonar.cluster.hosts must not contain a loopback address: remote_hz_host_2"); verifyLoopbackChecked(settings, - of("remote_hz_host_1", "remote_hz_host_2"), + ImmutableList.of("remote_hz_host_1", "remote_hz_host_2"), "Property sonar.cluster.hosts must not contain a loopback address: remote_hz_host_1, remote_hz_host_2"); } @Test public void ensure_no_loopback_host_in_properties_of_SEARCH_node() { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") - .set(CLUSTER_NODE_ES_HOST.getKey(), "transport_host"); - - verifyLoopbackChecked(settings, of("search_host"), "Property sonar.cluster.node.search.host must be a local non-loopback address: search_host"); - verifyLoopbackChecked(settings, of("transport_host"), "Property sonar.cluster.node.es.host must be a local non-loopback address: transport_host"); - verifyLoopbackChecked(settings, of("remote_search_host_1"), "Property sonar.cluster.es.hosts must not contain a loopback address: remote_search_host_1"); - verifyLoopbackChecked(settings, of("remote_search_host_2"), "Property sonar.cluster.es.hosts must not contain a loopback address: remote_search_host_2"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search") + .put(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") + .put(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") + .put(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") + .build()); + + verifyLoopbackChecked(settings, ImmutableList.of("search_host"), "Property sonar.cluster.node.search.host must be a local non-loopback address: search_host"); + verifyLoopbackChecked(settings, ImmutableList.of("transport_host"), "Property sonar.cluster.node.es.host must be a local non-loopback address: transport_host"); + verifyLoopbackChecked(settings, ImmutableList.of("remote_search_host_1"), "Property sonar.cluster.es.hosts must not contain a loopback address: remote_search_host_1"); + verifyLoopbackChecked(settings, ImmutableList.of("remote_search_host_2"), "Property sonar.cluster.es.hosts must not contain a loopback address: remote_search_host_2"); verifyLoopbackChecked(settings, - of("remote_search_host_1", "remote_search_host_2"), + ImmutableList.of("remote_search_host_1", "remote_search_host_2"), "Property sonar.cluster.es.hosts must not contain a loopback address: remote_search_host_1, remote_search_host_2"); } @@ -440,26 +449,28 @@ public class ClusterSettingsTest { @Test public void ensure_HZ_HOST_is_local_non_loopback_in_properties_of_APP_node() { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "application") - .set(CLUSTER_NODE_HOST.getKey(), "hz_host") - .set(CLUSTER_HZ_HOSTS.getKey(), "remote_hz_host_1,remote_hz_host_2") - .set(CLUSTER_SEARCH_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") - .set(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar") - .set("sonar.auth.jwtBase64Hs256Secret", "abcde"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "application") + .put(CLUSTER_NODE_HOST.getKey(), "hz_host") + .put(CLUSTER_HZ_HOSTS.getKey(), "remote_hz_host_1,remote_hz_host_2") + .put(CLUSTER_SEARCH_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") + .put(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar") + .put("sonar.auth.jwtBase64Hs256Secret", "abcde") + .build()); verifyLocalChecked(settings, "hz_host", "Property sonar.cluster.node.host must be a local non-loopback address: hz_host"); } @Test public void ensure_HZ_HOST_and_SEARCH_HOST_are_local_non_loopback_in_properties_of_SEARCH_node() { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") - .set(CLUSTER_NODE_ES_HOST.getKey(), "search_host"); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search") + .put(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001") + .put(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") + .put(CLUSTER_NODE_ES_HOST.getKey(), "search_host") + .build()); verifyLocalChecked(settings, "search_host", "Property sonar.cluster.node.search.host must be a local non-loopback address: search_host"); } @@ -484,17 +495,18 @@ public class ClusterSettingsTest { mockAllHostsValid(); mockLocalNonLoopback("search_host", "transport_host"); - verifyAllHostsWithPortsOrAllHostsWithoutPortsIsValid(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1, remote_search_host_2"); - verifyAllHostsWithPortsOrAllHostsWithoutPortsIsValid(CLUSTER_ES_HOSTS.getKey(), "remote_search_host_1:9001, remote_search_host_2:9001"); + verifyAllHostsWithPortsOrAllHostsWithoutPortsIsValid("remote_search_host_1, remote_search_host_2"); + verifyAllHostsWithPortsOrAllHostsWithoutPortsIsValid("remote_search_host_1:9001, remote_search_host_2:9001"); } - private void verifyAllHostsWithPortsOrAllHostsWithoutPortsIsValid(String propertyKey, String searchPropertyValue) { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") - .set(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") - .set(propertyKey, searchPropertyValue); + private void verifyAllHostsWithPortsOrAllHostsWithoutPortsIsValid(String searchPropertyValue) { + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search") + .put(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") + .put(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") + .put(CLUSTER_ES_HOSTS.getKey(), searchPropertyValue) + .build()); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -514,13 +526,14 @@ public class ClusterSettingsTest { } private void verifyAnyHostsConfigurationIsValid(String searchPropertyValue) { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") - .set(CLUSTER_ES_HOSTS.getKey(), "transport_host,transport_host") - .set(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") - .set(CLUSTER_SEARCH_HOSTS.getKey(), searchPropertyValue); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search") + .put(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") + .put(CLUSTER_ES_HOSTS.getKey(), "transport_host,transport_host") + .put(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") + .put(CLUSTER_SEARCH_HOSTS.getKey(), searchPropertyValue) + .build()); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -538,12 +551,13 @@ public class ClusterSettingsTest { } private void verifyPortsAreCheckedOnEsNode(String searchPropertyValue) { - TestAppSettings settings = new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") - .set(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") - .set(CLUSTER_ES_HOSTS.getKey(), searchPropertyValue); + TestAppSettings settings = new TestAppSettings(ImmutableMap.builder() + .put(CLUSTER_ENABLED.getKey(), "true") + .put(CLUSTER_NODE_TYPE.getKey(), "search") + .put(CLUSTER_NODE_SEARCH_HOST.getKey(), "search_host") + .put(CLUSTER_NODE_ES_HOST.getKey(), "transport_host") + .put(CLUSTER_ES_HOSTS.getKey(), searchPropertyValue) + .build()); ClusterSettings clusterSettings = new ClusterSettings(network); Props props = settings.getProps(); @@ -611,25 +625,37 @@ public class ClusterSettingsTest { } private TestAppSettings newSettingsForAppNode(String host) { - return new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "application") - .set(CLUSTER_NODE_HOST.getKey(), host) - .set(CLUSTER_HZ_HOSTS.getKey(), host) - .set(CLUSTER_SEARCH_HOSTS.getKey(), host + ":9001") - .set("sonar.auth.jwtBase64Hs256Secret", "abcde") - .set(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar"); + return newSettingsForAppNode(host, of()); + } + + private TestAppSettings newSettingsForAppNode(String host, ImmutableMap settings) { + Map result = new HashMap<>(); + result.put(CLUSTER_ENABLED.getKey(), "true"); + result.put(CLUSTER_NODE_TYPE.getKey(), "application"); + result.put(CLUSTER_NODE_HOST.getKey(), host); + result.put(CLUSTER_HZ_HOSTS.getKey(), host); + result.put(CLUSTER_SEARCH_HOSTS.getKey(), host + ":9001"); + result.put("sonar.auth.jwtBase64Hs256Secret", "abcde"); + result.put(JDBC_URL.getKey(), "jdbc:postgresql://localhost/sonar"); + result.putAll(settings); + return new TestAppSettings(result); } private TestAppSettings newSettingsForSearchNode(String host) { - return new TestAppSettings() - .set(CLUSTER_ENABLED.getKey(), "true") - .set(CLUSTER_NODE_TYPE.getKey(), "search") - .set(CLUSTER_NODE_HOST.getKey(), host) - .set(CLUSTER_HZ_HOSTS.getKey(), host) - .set(CLUSTER_ES_HOSTS.getKey(), host + ":9001") - .set(CLUSTER_NODE_SEARCH_HOST.getKey(), host) - .set(CLUSTER_NODE_ES_HOST.getKey(), host); + return newSettingsForSearchNode(host, of()); + } + + private TestAppSettings newSettingsForSearchNode(String host, ImmutableMap settings) { + Map result = new HashMap<>(); + result.put(CLUSTER_ENABLED.getKey(), "true"); + result.put(CLUSTER_NODE_TYPE.getKey(), "search"); + result.put(CLUSTER_NODE_HOST.getKey(), host); + result.put(CLUSTER_HZ_HOSTS.getKey(), host); + result.put(CLUSTER_ES_HOSTS.getKey(), host + ":9001"); + result.put(CLUSTER_NODE_SEARCH_HOST.getKey(), host); + result.put(CLUSTER_NODE_ES_HOST.getKey(), host); + result.putAll(settings); + return new TestAppSettings(result); } } diff --git a/server/sonar-main/src/test/java/org/sonar/application/config/TestAppSettings.java b/server/sonar-main/src/test/java/org/sonar/application/config/TestAppSettings.java index 64a3adbdbfa..5e0ef3d82df 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/config/TestAppSettings.java +++ b/server/sonar-main/src/test/java/org/sonar/application/config/TestAppSettings.java @@ -19,7 +19,9 @@ */ package org.sonar.application.config; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import java.util.Map; import java.util.Optional; import java.util.Properties; import org.sonar.core.extension.ServiceLoaderWrapper; @@ -38,17 +40,18 @@ public class TestAppSettings implements AppSettings { private Props props; public TestAppSettings() { - this.props = new Props(new Properties()); + this(ImmutableMap.of()); + } + + public TestAppSettings(Map initialSettings) { + Properties properties = new Properties(); + properties.putAll(initialSettings); + this.props = new Props(properties); ServiceLoaderWrapper serviceLoaderWrapper = mock(ServiceLoaderWrapper.class); when(serviceLoaderWrapper.load()).thenReturn(ImmutableSet.of()); new ProcessProperties(serviceLoaderWrapper).completeDefaults(this.props); } - public TestAppSettings set(String key, String value) { - this.props.set(key, value); - return this; - } - @Override public Props getProps() { return props; diff --git a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java index 747caf1e3c5..a1e7089900f 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java +++ b/server/sonar-process/src/main/java/org/sonar/process/ProcessProperties.java @@ -35,6 +35,9 @@ import org.sonar.core.extension.ServiceLoaderWrapper; import static com.google.common.base.Preconditions.checkState; import static java.lang.String.format; +import static org.sonar.process.ProcessProperties.Property.CLUSTER_ENABLED; +import static org.sonar.process.ProcessProperties.Property.SEARCH_HOST; +import static org.sonar.process.ProcessProperties.Property.SEARCH_PORT; /** * Constants shared by search, web server and app processes. @@ -72,8 +75,8 @@ public class ProcessProperties { LOG_MAX_FILES("sonar.log.maxFiles"), LOG_CONSOLE("sonar.log.console"), - SEARCH_HOST("sonar.search.host", InetAddress.getLoopbackAddress().getHostAddress()), - SEARCH_PORT("sonar.search.port", "9001"), + SEARCH_HOST("sonar.search.host"), + SEARCH_PORT("sonar.search.port"), // FIXME default is 0 until we move out of usage of TransportClient and we can put the expected default: 9002 SEARCH_TRANSPORT_PORT("sonar.search.transportPort", "0"), SEARCH_JAVA_OPTS("sonar.search.javaOpts", "-Xmx512m -Xms512m -XX:MaxDirectMemorySize=256m -XX:+HeapDumpOnOutOfMemoryError"), @@ -231,9 +234,14 @@ public class ProcessProperties { props.setDefault(entry.getKey().toString(), entry.getValue().toString()); } - fixPortIfZero(props, Property.SEARCH_HOST.getKey(), Property.SEARCH_PORT.getKey()); - // FIXME remove when transport is not used anymore in non-DCE editions: sonar.search.transportPort must not support port 0 - fixPortIfZero(props, Property.SEARCH_HOST.getKey(), Property.SEARCH_TRANSPORT_PORT.getKey()); + boolean clusterEnabled = props.valueAsBoolean(CLUSTER_ENABLED.getKey(), false); + if (!clusterEnabled) { + props.setDefault(SEARCH_HOST.getKey(), InetAddress.getLoopbackAddress().getHostAddress()); + props.setDefault(SEARCH_PORT.getKey(), "9001"); + fixPortIfZero(props, Property.SEARCH_HOST.getKey(), SEARCH_PORT.getKey()); + // FIXME remove when transport is not used anymore in non-DCE editions: sonar.search.transportPort must not support port 0 + fixPortIfZero(props, Property.SEARCH_HOST.getKey(), Property.SEARCH_TRANSPORT_PORT.getKey()); + } } private Properties defaults() { diff --git a/server/sonar-process/src/test/java/org/sonar/process/ProcessPropertiesTest.java b/server/sonar-process/src/test/java/org/sonar/process/ProcessPropertiesTest.java index f9022e2c6a2..9141871fb42 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/ProcessPropertiesTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/ProcessPropertiesTest.java @@ -32,6 +32,7 @@ import org.sonar.core.extension.CoreExtension; import org.sonar.core.extension.ServiceLoaderWrapper; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.sonar.process.ProcessProperties.parseTimeoutMs; @@ -40,8 +41,8 @@ public class ProcessPropertiesTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - private ServiceLoaderWrapper serviceLoaderWrapper = mock(ServiceLoaderWrapper.class); - private ProcessProperties processProperties = new ProcessProperties(serviceLoaderWrapper); + private final ServiceLoaderWrapper serviceLoaderWrapper = mock(ServiceLoaderWrapper.class); + private final ProcessProperties processProperties = new ProcessProperties(serviceLoaderWrapper); @Test public void completeDefaults_adds_default_values() { @@ -67,8 +68,9 @@ public class ProcessPropertiesTest { } @Test - public void completeDefaults_set_default_elasticsearch_port_and_bind_address() throws Exception { + public void completeDefaults_sets_default_values_for_sonar_search_host_and_sonar_search_port_in_non_cluster_mode() throws Exception { Properties p = new Properties(); + p.setProperty("sonar.cluster.enabled", "false"); Props props = new Props(p); processProperties.completeDefaults(props); @@ -80,14 +82,37 @@ public class ProcessPropertiesTest { } @Test - public void completeDefaults_sets_the_port_of_elasticsearch_if_value_is_zero() { + public void completeDefaults_does_not_set_default_values_for_sonar_search_host_and_sonar_search_port_in_cluster_mode() { + Properties p = new Properties(); + p.setProperty("sonar.cluster.enabled", "true"); + Props props = new Props(p); + + processProperties.completeDefaults(props); + + assertThat(props.contains("sonar.search.port")).isFalse(); + assertThat(props.contains("sonar.search.port")).isFalse(); + } + + @Test + public void completeDefaults_sets_the_transport_port_of_elasticsearch_if_value_is_zero_in_cluster_mode() { Properties p = new Properties(); p.setProperty("sonar.search.port", "0"); Props props = new Props(p); processProperties.completeDefaults(props); - assertThat(props.valueAsInt("sonar.search.port")).isGreaterThan(0); + assertThat(props.valueAsInt("sonar.search.port")).isPositive(); + } + + @Test + public void completeDefaults_sets_the_search_port_of_elasticsearch_if_value_is_zero_in_search_node_in_cluster() { + Properties p = new Properties(); + p.setProperty("sonar.search.port", "0"); + Props props = new Props(p); + + processProperties.completeDefaults(props); + + assertThat(props.valueAsInt("sonar.search.port")).isPositive(); } @Test @@ -109,10 +134,10 @@ public class ProcessPropertiesTest { public void defaults_throws_exception_on_same_property_defined_more_than_once_in_extensions() { Props p = new Props(new Properties()); when(serviceLoaderWrapper.load()).thenReturn(ImmutableSet.of(new FakeExtension1(), new FakeExtension2())); - expectedException.expect(IllegalStateException.class); - expectedException.expectMessage("Configuration error: property definition named 'sonar.some.property2' found in multiple extensions."); - processProperties.completeDefaults(p); + assertThatThrownBy(() -> processProperties.completeDefaults(p)) + .isInstanceOf(IllegalStateException.class) + .hasMessage("Configuration error: property definition named 'sonar.some.property2' found in multiple extensions."); } private static class FakeExtension1 implements CoreExtension { -- 2.39.5