diff options
author | Michal Duda <michal.duda@sonarsource.com> | 2020-10-27 23:02:20 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2020-11-05 20:06:21 +0000 |
commit | 8493c2b1bb1921573bd5a4a84d34b7b8c24d52da (patch) | |
tree | 22ff73cf4bfb899e8decece1b51ef347e6b5e52e /server/sonar-main | |
parent | 15bfd33b82de889b720af0539ae3ac0068106265 (diff) | |
download | sonarqube-8493c2b1bb1921573bd5a4a84d34b7b8c24d52da.tar.gz sonarqube-8493c2b1bb1921573bd5a4a84d34b7b8c24d52da.zip |
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
Diffstat (limited to 'server/sonar-main')
10 files changed, 338 insertions, 258 deletions
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<Props> { + private static final Set<Property> FORBIDDEN_SEARCH_NODE_SETTINGS = EnumSet.of(SEARCH_HOST, SEARCH_PORT); private final NetworkUtils network; @@ -87,6 +91,7 @@ public class ClusterSettings implements Consumer<Props> { 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<Props> { return trimmedValue; } + private static void ensureNoSearchNodeForbiddenSettings(Props props) { + List<String> 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<String, String> 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<InetAddress> 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.<String, String>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<ProcessId> 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<ProcessId> 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.<String, String>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.<String, String>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.<String, String>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.<String, String>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<String, String> addRequiredNodeProperties(ImmutableMap.Builder<String, String> 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<String> logger = mock(Consumer.class); + @SuppressWarnings("unchecked") + private final Consumer<String> 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<String, String> settings) { + Map<String, String> 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<String, String> settings) { + Map<String, String> 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.<String, String>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.<String, String>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<String> 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.<String, String>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.<String, String>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.<String, String>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.<String, String>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.<String, String>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.<String, String>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.<String, String>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<String, String> settings) { + Map<String, String> 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<String, String> settings) { + Map<String, String> 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<String, String> 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; |