*/
public class HazelcastClientWrapperImpl implements Startable, HazelcastClientWrapper {
+ private static final String HAZELCAST_CLUSTER_NAME = "sonarqube";
private final ClientConfig hzConfig;
@VisibleForTesting
public HazelcastClientWrapperImpl(Configuration config) {
boolean clusterEnabled = config.getBoolean(ProcessProperties.CLUSTER_ENABLED).orElse(false);
- String clusterName = config.get(ProcessProperties.CLUSTER_NAME).orElse(null);
String clusterLocalEndPoint = config.get(ProcessProperties.CLUSTER_LOCALENDPOINT).orElse(null);
checkState(clusterEnabled, "Cluster is not enabled");
checkState(isNotEmpty(clusterLocalEndPoint), "LocalEndPoint have not been set");
- checkState(isNotEmpty(clusterName), "sonar.cluster.name is missing");
hzConfig = new ClientConfig();
- hzConfig.getGroupConfig().setName(clusterName);
+ hzConfig.getGroupConfig().setName(HAZELCAST_CLUSTER_NAME);
hzConfig.getNetworkConfig().addAddress(clusterLocalEndPoint);
// Tweak HazelCast configuration
@BeforeClass
public static void setupHazelcastClusterAndHazelcastClient() {
int port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
- hzCluster = HazelcastTestHelper.createHazelcastCluster("cluster_with_client", port);
+ hzCluster = HazelcastTestHelper.createHazelcastCluster(port);
- MapSettings settings = createClusterSettings("cluster_with_client", "localhost:" + port);
+ MapSettings settings = createClusterSettings("localhost:" + port);
hzClient = new HazelcastClientWrapperImpl(settings.asConfig());
}
@Test
public void start_throws_ISE_if_LOCALENDPOINT_is_incorrect() {
- MapSettings settings = createClusterSettings("sonarqube", "\u4563\u1432\u1564");
+ MapSettings settings = createClusterSettings("\u4563\u1432\u1564");
HazelcastClientWrapperImpl hzClient = new HazelcastClientWrapperImpl(settings.asConfig());
expectedException.expect(IllegalStateException.class);
@Test
public void constructor_throws_ISE_if_LOCALENDPOINT_is_empty() {
- MapSettings settings = createClusterSettings("sonarqube", "");
+ MapSettings settings = createClusterSettings("");
expectedException.expect(IllegalStateException.class);
expectedException.expectMessage("LocalEndPoint have not been set");
@Test
public void constructor_throws_ISE_if_CLUSTER_ENABLED_is_false() {
- MapSettings settings = createClusterSettings("sonarqube", "localhost:9003");
+ MapSettings settings = createClusterSettings("localhost:9003");
settings.setProperty(ProcessProperties.CLUSTER_ENABLED, false);
expectedException.expect(IllegalStateException.class);
@Test
public void constructor_throws_ISE_if_missing_CLUSTER_ENABLED() {
- MapSettings settings = createClusterSettings("sonarqube", "localhost:9003");
+ MapSettings settings = createClusterSettings("localhost:9003");
settings.removeProperty(ProcessProperties.CLUSTER_ENABLED);
expectedException.expect(IllegalStateException.class);
new HazelcastClientWrapperImpl(settings.asConfig());
}
- @Test
- public void constructor_throws_ISE_if_missing_CLUSTER_NAME() {
- MapSettings settings = createClusterSettings("sonarqube", "localhost:9003");
- settings.removeProperty(ProcessProperties.CLUSTER_NAME);
-
- expectedException.expect(IllegalStateException.class);
- expectedException.expectMessage("sonar.cluster.name is missing");
-
- new HazelcastClientWrapperImpl(settings.asConfig());
- }
-
@Test
public void constructor_throws_ISE_if_missing_CLUSTER_LOCALENDPOINT() {
- MapSettings settings = createClusterSettings("sonarqube", "localhost:9003");
+ MapSettings settings = createClusterSettings("localhost:9003");
settings.removeProperty(ProcessProperties.CLUSTER_LOCALENDPOINT);
expectedException.expect(IllegalStateException.class);
public void client_must_connect_to_hazelcast() throws InterruptedException {
int port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
// Launch a fake Hazelcast instance
- HazelcastInstance hzInstance = HazelcastTestHelper.createHazelcastCluster("client_must_connect_to_hazelcast", port);
- MapSettings settings = createClusterSettings("client_must_connect_to_hazelcast", "localhost:" + port);
+ HazelcastInstance hzInstance = HazelcastTestHelper.createHazelcastCluster(port);
+ MapSettings settings = createClusterSettings("localhost:" + port);
HazelcastClientWrapperImpl hazelcastClientWrapperImpl = new HazelcastClientWrapperImpl(settings.asConfig());
ClientListenerImpl clientListener = new ClientListenerImpl();
@Test
public void client_must_be_able_to_set_ReplicatedMap_objects() throws InterruptedException {
+ hzClient.start();
try {
- hzClient.start();
Set<String> setTest = new HashSet<>();
setTest.addAll(
@Test
public void client_must_be_able_to_retrieve_Set_objects() {
+ hzClient.start();
try {
- hzClient.start();
// Set
Set<String> setTest = new HashSet<>();
@Test
public void client_must_be_able_to_retrieve_List_objects() {
+ hzClient.start();
try {
- hzClient.start();
// List
List<String> listTest = Arrays.asList("1", "2");
@Test
public void client_must_be_able_to_retrieve_Map_objects() {
+ hzClient.start();
try {
- hzClient.start();
-
Map mapTest = new HashMap<>();
mapTest.put("a", Arrays.asList("123", "456"));
hzCluster.getMap("TEST3").putAll(mapTest);
@Test
public void configuration_tweaks_of_hazelcast_must_be_present() {
+ hzClient.start();
try {
- hzClient.start();
HazelcastClientInstanceImpl realClient = ((HazelcastClientProxy) hzClient.hzInstance).client;
assertThat(realClient.getClientConfig().getProperty("hazelcast.tcp.join.port.try.count")).isEqualTo("10");
assertThat(realClient.getClientConfig().getProperty("hazelcast.phone.home.enabled")).isEqualTo("false");
memoryAppender.start();
lc.getLogger("com.hazelcast").addAppender(memoryAppender);
- try {
- hzClient.start();
- } finally {
- hzClient.stop();
- memoryAppender.stop();
- }
+ hzClient.start();
+ hzClient.stop();
+ memoryAppender.stop();
assertThat(memoryAppender.events).isNotEmpty();
memoryAppender.events.stream().forEach(
e -> assertThat(e.getLoggerName()).startsWith("com.hazelcast"));
}
}
- private static MapSettings createClusterSettings(String name, String localEndPoint) {
+ private static MapSettings createClusterSettings(String localEndPoint) {
return new MapSettings(new PropertyDefinitions())
- .setProperty(ProcessProperties.CLUSTER_NAME, name)
.setProperty(ProcessProperties.CLUSTER_LOCALENDPOINT, localEndPoint)
.setProperty(ProcessProperties.CLUSTER_ENABLED, "true");
}
import com.hazelcast.core.HazelcastInstance;
import java.net.InetAddress;
-import static org.sonar.process.NetworkUtils.getHostName;
+import static org.sonar.process.NetworkUtils.getHostname;
import static org.sonar.process.cluster.ClusterObjectKeys.CLIENT_UUIDS;
public class HazelcastTestHelper {
- public static HazelcastInstance createHazelcastCluster(String clusterName, int port) {
+ public static HazelcastInstance createHazelcastCluster(int port) {
Config hzConfig = new Config();
- hzConfig.getGroupConfig().setName(clusterName);
+ hzConfig.getGroupConfig().setName("sonarqube");
// Configure the network instance
NetworkConfig netConfig = hzConfig.getNetworkConfig();
.setProperty("hazelcast.logging.type", "slf4j");
// Trying to resolve the hostname
- hzConfig.getMemberAttributeConfig().setStringAttribute("HOSTNAME", getHostName());
+ hzConfig.getMemberAttributeConfig().setStringAttribute("HOSTNAME", getHostname());
// We are not using the partition group of Hazelcast, so disabling it
hzConfig.getPartitionGroupConfig().setEnabled(false);
public class ComputeEngineContainerImplTest {
private static final int CONTAINER_ITSELF = 1;
private static final int COMPONENTS_IN_LEVEL_1_AT_CONSTRUCTION = CONTAINER_ITSELF + 1;
- private static final String CLUSTER_NAME = "test";
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
@Test
public void real_start_with_cluster() throws IOException {
int port = NetworkUtils.getNextAvailablePort(InetAddress.getLoopbackAddress());
- HazelcastInstance hzInstance = HazelcastTestHelper.createHazelcastCluster(CLUSTER_NAME, port);
+ HazelcastInstance hzInstance = HazelcastTestHelper.createHazelcastCluster(port);
Properties properties = getProperties();
properties.setProperty(ProcessProperties.CLUSTER_NODE_TYPE, "application");
properties.setProperty(ProcessProperties.CLUSTER_ENABLED, "true");
properties.setProperty(ProcessProperties.CLUSTER_LOCALENDPOINT, String.format("%s:%d", hzInstance.getCluster().getLocalMember().getAddress().getHost(), port));
- properties.setProperty(ProcessProperties.CLUSTER_NAME, CLUSTER_NAME);
// required persisted properties
insertProperty(CoreProperties.SERVER_ID, "a_startup_id");
void registerSonarQubeVersion(String sonarqubeVersion);
+ void registerClusterName(String clusterName);
+
Optional<String> getLeaderHostName();
@Override
// Nothing to do on non clustered version
}
+ @Override
+ public void registerClusterName(String clusterName) {
+ // Nothing to do on non clustered version
+ }
+
@Override
public Optional<String> getLeaderHostName() {
- return Optional.of(NetworkUtils.getHostName());
+ return Optional.of(NetworkUtils.getHostname());
}
@Override
appSettings.getProps().set(ProcessProperties.CLUSTER_MEMBERUUID, hazelcastCluster.getLocalUUID());
String members = hazelcastCluster.getMembers().stream().collect(Collectors.joining(","));
- LOGGER.info("Joined the cluster [{}] that contains the following hosts : [{}]", hazelcastCluster.getName(), members);
+ LOGGER.info("Joined a SonarQube cluster that contains the following hosts : [{}]", members);
}
@Override
hazelcastCluster.registerSonarQubeVersion(sonarqubeVersion);
}
+ @Override
+ public void registerClusterName(String clusterName) {
+ hazelcastCluster.registerClusterName(clusterName);
+ }
+
@Override
public Optional<String> getLeaderHostName() {
return hazelcastCluster.getLeaderHostName();
public final class ClusterProperties {
static final String DEFAULT_PORT = "9003";
private static final Logger LOGGER = LoggerFactory.getLogger(ClusterProperties.class);
+ public static final String HAZELCAST_CLUSTER_NAME = "sonarqube";
private final int port;
private final List<String> hosts;
private final List<String> networkInterfaces;
- private final String name;
private final NodeType nodeType;
ClusterProperties(AppSettings appSettings) {
networkInterfaces = extractNetworkInterfaces(
appSettings.getProps().value(ProcessProperties.CLUSTER_NODE_HOST, "")
);
- name = appSettings.getProps().nonNullValue(ProcessProperties.CLUSTER_NAME);
hosts = extractHosts(
appSettings.getProps().value(ProcessProperties.CLUSTER_HOSTS, "")
);
return networkInterfaces;
}
- String getName() {
- return name;
- }
-
void validate() {
// Test validity of port
checkArgument(
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.application.AppStateListener;
+import org.sonar.process.MessageException;
import org.sonar.process.NodeType;
import org.sonar.process.ProcessId;
+import static java.lang.String.format;
import static java.util.stream.Collectors.toList;
-import static org.sonar.process.NetworkUtils.getHostName;
+import static org.sonar.application.cluster.ClusterProperties.HAZELCAST_CLUSTER_NAME;
+import static org.sonar.process.NetworkUtils.getHostname;
+import static org.sonar.process.NetworkUtils.getIPAddresses;
import static org.sonar.process.cluster.ClusterObjectKeys.CLIENT_UUIDS;
+import static org.sonar.process.cluster.ClusterObjectKeys.CLUSTER_NAME;
import static org.sonar.process.cluster.ClusterObjectKeys.HOSTNAME;
+import static org.sonar.process.cluster.ClusterObjectKeys.IP_ADDRESSES;
import static org.sonar.process.cluster.ClusterObjectKeys.LEADER;
import static org.sonar.process.cluster.ClusterObjectKeys.NODE_TYPE;
import static org.sonar.process.cluster.ClusterObjectKeys.OPERATIONAL_PROCESSES;
List<String> getMembers() {
return hzInstance.getCluster().getMembers().stream()
.filter(m -> !m.localMember())
- .map(m -> m.getStringAttribute(HOSTNAME))
+ .map(m -> format("%s (%s)", m.getStringAttribute(HOSTNAME), m.getStringAttribute(IP_ADDRESSES)))
.collect(toList());
}
String clusterVersion = sqVersion.get();
if (!sqVersion.get().equals(sonarqubeVersion)) {
throw new IllegalStateException(
- String.format("The local version %s is not the same as the cluster %s", sonarqubeVersion, clusterVersion)
+ format("The local version %s is not the same as the cluster %s", sonarqubeVersion, clusterVersion)
+ );
+ }
+ }
+
+ public void registerClusterName(String nodeValue) {
+ IAtomicReference<String> property = hzInstance.getAtomicReference(CLUSTER_NAME);
+ if (property.get() == null) {
+ ILock lock = hzInstance.getLock(CLUSTER_NAME);
+ lock.lock();
+ try {
+ if (property.get() == null) {
+ property.set(nodeValue);
+ }
+ } finally {
+ lock.unlock();
+ }
+ }
+
+ String clusterValue = property.get();
+ if (!property.get().equals(nodeValue)) {
+ throw new MessageException(
+ format("This node has a cluster name [%s], which does not match [%s] from the cluster", nodeValue, clusterValue)
);
}
}
public static HazelcastCluster create(ClusterProperties clusterProperties) {
Config hzConfig = new Config();
- hzConfig.getGroupConfig().setName(clusterProperties.getName());
+ hzConfig.getGroupConfig().setName(HAZELCAST_CLUSTER_NAME);
// Configure the network instance
NetworkConfig netConfig = hzConfig.getNetworkConfig();
// Trying to resolve the hostname
hzConfig.getMemberAttributeConfig()
- .setStringAttribute(HOSTNAME, getHostName());
+ .setStringAttribute(HOSTNAME, getHostname());
+ hzConfig.getMemberAttributeConfig()
+ .setStringAttribute(IP_ADDRESSES, getIPAddresses());
hzConfig.getMemberAttributeConfig()
.setStringAttribute(NODE_TYPE, clusterProperties.getNodeType().getValue());
if (leaderId != null) {
Optional<Member> leader = hzInstance.getCluster().getMembers().stream().filter(m -> m.getUuid().equals(leaderId)).findFirst();
if (leader.isPresent()) {
- return Optional.of(leader.get().getStringAttribute(HOSTNAME));
+ return Optional.of(
+ format("%s (%s)", leader.get().getStringAttribute(HOSTNAME), leader.get().getStringAttribute(IP_ADDRESSES)));
}
}
return Optional.empty();
String getLocalEndPoint() {
Address localAddress = hzInstance.getCluster().getLocalMember().getAddress();
- return String.format("%s:%d", localAddress.getHost(), localAddress.getPort());
+ return format("%s:%d", localAddress.getHost(), localAddress.getPort());
}
private class OperationalProcessListener implements EntryListener<ClusterProcess, Boolean> {
// nothing to do
}
+ @Override
+ public void registerClusterName(String clusterName) {
+ // nothing to do
+ }
+
@Override
public Optional<String> getLeaderHostName() {
- return Optional.of(NetworkUtils.getHostName());
+ return Optional.of(NetworkUtils.getHostname());
}
@Override
import org.slf4j.Logger;
import org.sonar.application.AppStateListener;
import org.sonar.application.config.TestAppSettings;
+import org.sonar.process.MessageException;
import org.sonar.process.ProcessId;
import org.sonar.process.ProcessProperties;
+import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
import static org.sonar.application.cluster.HazelcastTestHelper.createHazelcastClient;
import static org.sonar.application.cluster.HazelcastTestHelper.newClusterSettings;
+import static org.sonar.process.cluster.ClusterObjectKeys.CLUSTER_NAME;
import static org.sonar.process.cluster.ClusterObjectKeys.SONARQUBE_VERSION;
public class AppStateClusterImplTest {
try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
verify(logger).info(
- eq("Joined the cluster [{}] that contains the following hosts : [{}]"),
- eq("sonarqube"),
+ eq("Joined a SonarQube cluster that contains the following hosts : [{}]"),
anyString()
);
}
}
}
+ @Test
+ public void registerClusterName_publishes_clusterName_on_first_call() {
+ TestAppSettings settings = newClusterSettings();
+ String clusterName = randomAlphanumeric(20);
+
+ try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
+ appStateCluster.registerClusterName(clusterName);
+
+ HazelcastInstance hzInstance = createHazelcastClient(appStateCluster);
+ assertThat(hzInstance.getAtomicReference(CLUSTER_NAME).get())
+ .isNotNull()
+ .isInstanceOf(String.class)
+ .isEqualTo(clusterName);
+ }
+ }
+
@Test
public void reset_throws_always_ISE() {
TestAppSettings settings = newClusterSettings();
appStateCluster.registerSonarQubeVersion("2.0.0");
}
}
+
+ @Test
+ public void registerClusterName_throws_MessageException_if_clusterName_is_different() throws Exception {
+ // Now launch an instance that try to be part of the hzInstance cluster
+ TestAppSettings settings = newClusterSettings();
+
+ try (AppStateClusterImpl appStateCluster = new AppStateClusterImpl(settings)) {
+ // Register first version
+ appStateCluster.registerClusterName("goodClusterName");
+
+ expectedException.expect(MessageException.class);
+ expectedException.expectMessage("This node has a cluster name [badClusterName], which does not match [goodClusterName] from the cluster");
+
+ // Registering a second different cluster name must trigger an exception
+ appStateCluster.registerClusterName("badClusterName");
+ }
+ }
}
.isEqualTo(9003);
assertThat(props.getHosts())
.isEqualTo(Collections.emptyList());
- assertThat(props.getName())
- .isEqualTo("sonarqube");
}
@Test
import org.sonar.process.ProcessProperties;
import org.sonar.process.cluster.ClusterObjectKeys;
+import static java.lang.String.format;
import static junit.framework.TestCase.fail;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
ClusterProperties clusterProperties = new ClusterProperties(newClusterSettings());
try (HazelcastCluster hzCluster = HazelcastCluster.create(clusterProperties)) {
assertThat(hzCluster.tryToLockWebLeader()).isTrue();
- assertThat(hzCluster.getLeaderHostName().get()).isEqualTo(NetworkUtils.getHostName());
+ assertThat(hzCluster.getLeaderHostName().get()).isEqualTo(
+ format("%s (%s)", NetworkUtils.getHostname(), NetworkUtils.getIPAddresses()));
}
}
}
@Test
- public void cluster_name_comes_from_configuration() {
+ public void hazelcast_cluster_name_is_hardcoded_and_not_affected_by_settings() {
TestAppSettings testAppSettings = newClusterSettings();
testAppSettings.set(CLUSTER_NAME, "a_cluster_");
ClusterProperties clusterProperties = new ClusterProperties(testAppSettings);
try (HazelcastCluster hzCluster = HazelcastCluster.create(clusterProperties)) {
- assertThat(hzCluster.getName()).isEqualTo("a_cluster_");
+ assertThat(hzCluster.getName()).isEqualTo("sonarqube");
}
}
import java.util.Set;
import java.util.stream.Collectors;
-import static java.lang.String.format;
import static java.util.Collections.list;
import static org.apache.commons.lang.StringUtils.isBlank;
/**
* Identifying the localhost machine
- * It will try to retrieve the hostname and the IPv4 addresses
+ * It will try to retrieve the hostname
*
- * @return "hostname (ipv4_1, ipv4_2...)"
+ * @return "hostname"
*/
- public static String getHostName() {
+ public static String getHostname() {
String hostname;
- String ips;
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
hostname = "unresolved hostname";
}
+ return hostname;
+ }
+
+ /**
+ * Identifying the IPs addresses
+ *
+ * @return "ipv4_1, ipv4_2"
+ */
+ public static String getIPAddresses() {
+ String ips;
+
try {
ips = list(NetworkInterface.getNetworkInterfaces()).stream()
.flatMap(netif -> list(netif.getInetAddresses()).stream()
.filter(inetAddress ->
- // Removing IPv6 for the time being
- inetAddress instanceof Inet4Address &&
- // Removing loopback addresses, useless for identifying a server
- !inetAddress.isLoopbackAddress() &&
- // Removing interfaces without IPs
- !isBlank(inetAddress.getHostAddress()))
+ // Removing IPv6 for the time being
+ inetAddress instanceof Inet4Address &&
+ // Removing loopback addresses, useless for identifying a server
+ !inetAddress.isLoopbackAddress() &&
+ // Removing interfaces without IPs
+ !isBlank(inetAddress.getHostAddress()))
.map(InetAddress::getHostAddress))
.filter(p -> !isBlank(p))
.collect(Collectors.joining(","));
ips = "unresolved IPs";
}
- return format("%s (%s)", hostname, ips);
+ return ips;
}
/**
* The key of the hostname attribute of a member
*/
public static final String HOSTNAME = "HOSTNAME";
+ /**
+ * The key of the ips list attribute of a member
+ */
+ public static final String IP_ADDRESSES = "IP_ADDRESSES";
+ /**
+ * The key of the node name attribute of a member
+ */
+ public static final String NODE_NAME = "NODE_NAME";
/**
* The role of the sonar-application inside the SonarQube cluster
* The key of atomic reference holding the SonarQube version of the cluster
*/
public static final String SONARQUBE_VERSION = "SONARQUBE_VERSION";
+ /**
+ * The key of atomic reference holding the name of the cluster (used for precondition checks)
+ */
+ public static final String CLUSTER_NAME = "CLUSTER_NAME";
/**
* The key of the Set holding the UUIDs of clients
*/
}
@Test
- public void getHostName_must_return_a_value() {
- assertThat(NetworkUtils.getHostName()).containsPattern(".* \\(.*\\)");
+ public void getHostname_must_return_a_value() {
+ assertThat(NetworkUtils.getHostname()).containsPattern(".+");
+ }
+
+ @Test
+ public void getIPAddresses_must_return_a_value() {
+ assertThat(NetworkUtils.getIPAddresses()).matches("(\\d+\\.\\d+\\.\\d+\\.\\d+,?)+");
}
}
import org.sonar.process.SystemExit;
import static org.sonar.application.config.SonarQubeVersionHelper.getSonarqubeVersion;
+import static org.sonar.process.ProcessProperties.CLUSTER_NAME;
public class App {
try (AppState appState = new AppStateFactory(settings).create()) {
appState.registerSonarQubeVersion(getSonarqubeVersion());
+ appState.registerClusterName(settings.getProps().value(CLUSTER_NAME, "sonarqube"));
AppReloader appReloader = new AppReloaderImpl(settingsLoader, fileSystem, appState, logging);
fileSystem.reset();
CommandFactory commandFactory = new CommandFactoryImpl(settings.getProps(), fileSystem.getTempDir());
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
+import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull;
return new Cluster(nodes);
}
- public Builder addNode(NodeType type) {
- nodes.add(new Node(type));
+ public Builder addNode(NodeType type, Consumer<Node>... consumers) {
+ Node node = new Node(type);
+ Arrays.stream(consumers).forEach(c -> c.accept(node));
+ nodes.add(node);
return this;
}
}
dce.stop();
}
+ @Test
+ public void using_different_cluster_names_should_fail() throws ExecutionException, InterruptedException, SQLException {
+ Cluster cluster = Cluster.builder()
+ .addNode(SEARCH, n -> n.getProperties().setProperty(Cluster.CLUSTER_NAME, "goodClusterName"))
+ .addNode(SEARCH, n -> n.getProperties().setProperty(Cluster.CLUSTER_NAME, "goodClusterName"))
+ .addNode(SEARCH, n -> n.getProperties().setProperty(Cluster.CLUSTER_NAME, "goodClusterName"))
+ .addNode(APPLICATION, n -> n.getProperties().setProperty(Cluster.CLUSTER_NAME, "goodClusterName"))
+ .addNode(APPLICATION, n -> n.getProperties().setProperty(Cluster.CLUSTER_NAME, "badClusterName"))
+ .build();
+ cluster.startAll(n -> "goodClusterName".equals(n.getProperties().getProperty(Cluster.CLUSTER_NAME)));
+
+ try {
+ cluster.startAll(n -> "badClusterName".equals(n.getProperties().getProperty(Cluster.CLUSTER_NAME)));
+ fail("A node with a bad cluster name was able to join the cluster");
+ } catch (Exception e) {
+ // we expect, that joining the cluster fails
+ System.out.println(e);
+ }
+ }
+
private void assertDatabaseInitialized(Database database) {
assertThat(countRowsOfMigration(database)).isGreaterThan(0);
}