From 78a0a38cd36db3d2c38ffd7ccc494bcd9d366ad9 Mon Sep 17 00:00:00 2001 From: Jacek Date: Thu, 22 Jul 2021 13:52:18 +0200 Subject: [PATCH] SONAR-15230 Enable DNS lookup in k8s for HZ --- build.gradle | 1 + server/sonar-ce/build.gradle | 1 + .../src/pages/setup/upgrade-notes.md | 2 +- .../sonar/application/AppStateFactory.java | 7 +- .../cluster/ClusterAppStateImplTest.java | 4 +- server/sonar-process/build.gradle | 1 + .../org/sonar/process/ProcessProperties.java | 1 + .../cluster/hz/HazelcastMemberBuilder.java | 78 +++++------------ .../cluster/hz/JoinConfigurationType.java | 25 ++++++ .../process/cluster/hz/MembersResolver.java | 26 ++++++ ...sResolver.java => NopMembersResolver.java} | 12 +-- .../cluster/hz/TcpIpMembersResolver.java | 74 ++++++++++++++++ .../hz/HazelcastMemberBuilderTest.java | 86 ++++++++++--------- .../cluster/hz/HazelcastMemberImplTest.java | 2 +- 14 files changed, 210 insertions(+), 110 deletions(-) create mode 100644 server/sonar-process/src/main/java/org/sonar/process/cluster/hz/JoinConfigurationType.java create mode 100644 server/sonar-process/src/main/java/org/sonar/process/cluster/hz/MembersResolver.java rename server/sonar-process/src/main/java/org/sonar/process/cluster/hz/{InetAdressResolver.java => NopMembersResolver.java} (71%) create mode 100644 server/sonar-process/src/main/java/org/sonar/process/cluster/hz/TcpIpMembersResolver.java diff --git a/build.gradle b/build.gradle index f4ee139085c..73acd5aa37f 100644 --- a/build.gradle +++ b/build.gradle @@ -332,6 +332,7 @@ subprojects { dependencySet(group: 'com.hazelcast', version: '4.2') { entry 'hazelcast' } + dependency 'com.hazelcast:hazelcast-kubernetes:2.2.3' dependency 'com.ibm.icu:icu4j:3.4.4' dependency 'com.microsoft.sqlserver:mssql-jdbc:9.2.0.jre11' dependency 'com.oracle.database.jdbc:ojdbc8:19.3.0.0' diff --git a/server/sonar-ce/build.gradle b/server/sonar-ce/build.gradle index 8a3a736e2d5..1cb412e850d 100644 --- a/server/sonar-ce/build.gradle +++ b/server/sonar-ce/build.gradle @@ -11,6 +11,7 @@ dependencies { compile 'com.google.guava:guava' compile 'com.google.protobuf:protobuf-java' compile 'com.hazelcast:hazelcast' + compile 'com.hazelcast:hazelcast-kubernetes' compile 'commons-io:commons-io' compile 'org.apache.commons:commons-dbcp2' compile 'org.nanohttpd:nanohttpd' diff --git a/server/sonar-docs/src/pages/setup/upgrade-notes.md b/server/sonar-docs/src/pages/setup/upgrade-notes.md index 07f968dc430..8394ab453cb 100644 --- a/server/sonar-docs/src/pages/setup/upgrade-notes.md +++ b/server/sonar-docs/src/pages/setup/upgrade-notes.md @@ -44,4 +44,4 @@ SonarQube 8.9 supports the following database versions: **Webhooks aren't allowed to target the instance** To improve security, webhooks, by default, aren't allowed to point to the SonarQube server. You can change this behavior in the configuration. ([SONAR-14682](https://jira.sonarsource.com/browse/SONAR-14682)). -[Full release notes](https://jira.sonarsource.com/secure/ReleaseNote.jspa?projectId=10930&version=16710) \ No newline at end of file +[Full release notes](https://jira.sonarsource.com/secure/ReleaseNote.jspa?projectId=10930&version=16710) diff --git a/server/sonar-main/src/main/java/org/sonar/application/AppStateFactory.java b/server/sonar-main/src/main/java/org/sonar/application/AppStateFactory.java index 936dcb64996..74541528cb2 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/AppStateFactory.java +++ b/server/sonar-main/src/main/java/org/sonar/application/AppStateFactory.java @@ -33,15 +33,17 @@ import org.sonar.process.ProcessId; import org.sonar.process.Props; import org.sonar.process.cluster.hz.HazelcastMember; import org.sonar.process.cluster.hz.HazelcastMemberBuilder; -import org.sonar.process.cluster.hz.InetAdressResolver; import static java.util.Arrays.asList; import static org.sonar.process.ProcessProperties.Property.CLUSTER_HZ_HOSTS; +import static org.sonar.process.ProcessProperties.Property.CLUSTER_KUBERNETES; import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HOST; import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HZ_PORT; import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_NAME; import static org.sonar.process.ProcessProperties.Property.CLUSTER_SEARCH_HOSTS; import static org.sonar.process.ProcessProperties.Property.CLUSTER_SEARCH_PASSWORD; +import static org.sonar.process.cluster.hz.JoinConfigurationType.KUBERNETES; +import static org.sonar.process.cluster.hz.JoinConfigurationType.TCP_IP; public class AppStateFactory { private final AppSettings settings; @@ -61,7 +63,8 @@ public class AppStateFactory { } private static HazelcastMember createHzMember(Props props) { - HazelcastMemberBuilder builder = new HazelcastMemberBuilder(new InetAdressResolver()) + boolean isRunningOnKubernetes = props.valueAsBoolean(CLUSTER_KUBERNETES.getKey(), Boolean.parseBoolean(CLUSTER_KUBERNETES.getDefaultValue())); + HazelcastMemberBuilder builder = new HazelcastMemberBuilder(isRunningOnKubernetes ? KUBERNETES : TCP_IP) .setNetworkInterface(props.nonNullValue(CLUSTER_NODE_HOST.getKey())) .setMembers(asList(props.nonNullValue(CLUSTER_HZ_HOSTS.getKey()).split(","))) .setNodeName(props.nonNullValue(CLUSTER_NODE_NAME.getKey())) diff --git a/server/sonar-main/src/test/java/org/sonar/application/cluster/ClusterAppStateImplTest.java b/server/sonar-main/src/test/java/org/sonar/application/cluster/ClusterAppStateImplTest.java index 1501f6f6243..16bbb81773b 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/cluster/ClusterAppStateImplTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/cluster/ClusterAppStateImplTest.java @@ -35,7 +35,7 @@ import org.sonar.process.NetworkUtilsImpl; import org.sonar.process.ProcessId; import org.sonar.process.cluster.hz.HazelcastMember; import org.sonar.process.cluster.hz.HazelcastMemberBuilder; -import org.sonar.process.cluster.hz.InetAdressResolver; +import org.sonar.process.cluster.hz.JoinConfigurationType; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -171,7 +171,7 @@ public class ClusterAppStateImplTest { // use loopback for support of offline builds InetAddress loopback = InetAddress.getLoopbackAddress(); - return new HazelcastMemberBuilder(new InetAdressResolver()) + return new HazelcastMemberBuilder(JoinConfigurationType.TCP_IP) .setProcessId(ProcessId.COMPUTE_ENGINE) .setNodeName("bar") .setPort(NetworkUtilsImpl.INSTANCE.getNextLoopbackAvailablePort()) diff --git a/server/sonar-process/build.gradle b/server/sonar-process/build.gradle index aef277baef4..e075136b8e1 100644 --- a/server/sonar-process/build.gradle +++ b/server/sonar-process/build.gradle @@ -16,6 +16,7 @@ dependencies { compile 'com.google.guava:guava' compile 'com.google.protobuf:protobuf-java' compile 'com.hazelcast:hazelcast' + compile 'com.hazelcast:hazelcast-kubernetes' compile 'org.slf4j:jul-to-slf4j' compile 'org.slf4j:slf4j-api' compile project(':sonar-core') 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 9217274a281..72c99d1b2d0 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 @@ -114,6 +114,7 @@ public class ProcessProperties { SOCKS_PROXY_PORT("socksProxyPort"), CLUSTER_ENABLED("sonar.cluster.enabled", "false"), + CLUSTER_KUBERNETES("sonar.cluster.kubernetes", "false"), CLUSTER_NODE_TYPE("sonar.cluster.node.type"), CLUSTER_SEARCH_HOSTS("sonar.cluster.search.hosts"), CLUSTER_HZ_HOSTS("sonar.cluster.hosts"), diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberBuilder.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberBuilder.java index c2552ef3e20..0e207d7050d 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberBuilder.java +++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/HazelcastMemberBuilder.java @@ -24,36 +24,29 @@ import com.hazelcast.config.JoinConfig; import com.hazelcast.config.MemberAttributeConfig; import com.hazelcast.config.NetworkConfig; import com.hazelcast.core.Hazelcast; -import com.hazelcast.internal.util.AddressUtil; -import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; -import javax.annotation.CheckForNull; -import org.sonar.api.utils.log.Logger; -import org.sonar.api.utils.log.Loggers; import org.sonar.process.ProcessId; import org.sonar.process.cluster.hz.HazelcastMember.Attribute; -import static java.lang.String.format; import static java.util.Collections.singletonList; import static java.util.Objects.requireNonNull; -import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HZ_PORT; +import static org.sonar.process.cluster.hz.JoinConfigurationType.KUBERNETES; +import static org.sonar.process.cluster.hz.JoinConfigurationType.TCP_IP; public class HazelcastMemberBuilder { - - private static final Logger LOG = Loggers.get(HazelcastMemberBuilder.class); private String nodeName; private int port; private ProcessId processId; private String networkInterface; - private List members = new ArrayList<>(); - private final InetAdressResolver inetAdressResolver; + private final MembersResolver membersResolver; + private final List members = new ArrayList<>(); + private final JoinConfigurationType type; - public HazelcastMemberBuilder(InetAdressResolver inetAdressResolver) { - this.inetAdressResolver = inetAdressResolver; + public HazelcastMemberBuilder(JoinConfigurationType type) { + this.type = type; + this.membersResolver = TCP_IP.equals(type) ? new TcpIpMembersResolver() : new NopMembersResolver(); } public HazelcastMemberBuilder setNodeName(String s) { @@ -79,49 +72,14 @@ public class HazelcastMemberBuilder { return this; } - @CheckForNull - List getMembers() { - return members; - } - /** - * Adds references to cluster members. If port is missing, then default - * port is automatically added. + * Adds references to cluster members */ - public HazelcastMemberBuilder setMembers(Collection c) { - this.members.addAll(c.stream().map(this::extractMembers).flatMap(Collection::stream).collect(Collectors.toList())); + public HazelcastMemberBuilder setMembers(Collection members) { + this.members.addAll(members); return this; } - private List extractMembers(String host) { - LOG.debug("Trying to add host: " + host); - String hostStripped = host.split(":")[0]; - if (AddressUtil.isIpAddress(hostStripped)) { - LOG.debug("Found ip based host config for host: " + host); - return Collections.singletonList(host.contains(":") ? host : format("%s:%s", host, CLUSTER_NODE_HZ_PORT.getDefaultValue())); - } else { - List membersToAdd = new ArrayList<>(); - for (String memberIp : getAllByName(hostStripped)) { - String prefix = memberIp.split("/")[1]; - LOG.debug("Found IP for: " + hostStripped + " : " + prefix); - String memberPort = host.contains(":") ? host.split(":")[1] : CLUSTER_NODE_HZ_PORT.getDefaultValue(); - String member = prefix + ":" + memberPort; - membersToAdd.add(member); - } - return membersToAdd; - } - } - - List getAllByName(String hostname) { - LOG.debug("Trying to resolve Hostname: " + hostname); - try { - return inetAdressResolver.getAllByName(hostname); - } catch (UnknownHostException e) { - LOG.error("Host could not be found\n" + e.getMessage()); - } - return new ArrayList<>(); - } - public HazelcastMember build() { Config config = new Config(); // do not use the value defined by property sonar.cluster.name. @@ -140,12 +98,20 @@ public class HazelcastMemberBuilder { .setEnabled(true) .setInterfaces(singletonList(requireNonNull(networkInterface, "Network interface is missing"))); - // Only allowing TCP/IP configuration JoinConfig joinConfig = netConfig.getJoin(); joinConfig.getAwsConfig().setEnabled(false); joinConfig.getMulticastConfig().setEnabled(false); - joinConfig.getTcpIpConfig().setEnabled(true); - joinConfig.getTcpIpConfig().setMembers(requireNonNull(members, "Members are missing")); + + List resolvedNodes = membersResolver.resolveMembers(this.members); + if (KUBERNETES.equals(type)) { + joinConfig.getKubernetesConfig().setEnabled(true) + .setProperty("service-dns", requireNonNull(resolvedNodes.get(0), "Service DNS is missing")) + .setProperty("service-port", "9003"); + } else { + joinConfig.getTcpIpConfig().setEnabled(true); + joinConfig.getTcpIpConfig().setMembers(requireNonNull(resolvedNodes, "Members are missing")); + } + // We are not using the partition group of Hazelcast, so disabling it config.getPartitionGroupConfig().setEnabled(false); diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/JoinConfigurationType.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/JoinConfigurationType.java new file mode 100644 index 00000000000..cb7765c62fb --- /dev/null +++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/JoinConfigurationType.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.process.cluster.hz; + +public enum JoinConfigurationType { + TCP_IP, + KUBERNETES +} diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/MembersResolver.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/MembersResolver.java new file mode 100644 index 00000000000..3419c8b0bc2 --- /dev/null +++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/MembersResolver.java @@ -0,0 +1,26 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.process.cluster.hz; + +import java.util.List; + +interface MembersResolver { + List resolveMembers(List membersToResolve); +} diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/InetAdressResolver.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/NopMembersResolver.java similarity index 71% rename from server/sonar-process/src/main/java/org/sonar/process/cluster/hz/InetAdressResolver.java rename to server/sonar-process/src/main/java/org/sonar/process/cluster/hz/NopMembersResolver.java index 3211a94ca9f..fbafb4f90f7 100644 --- a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/InetAdressResolver.java +++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/NopMembersResolver.java @@ -19,16 +19,12 @@ */ package org.sonar.process.cluster.hz; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; import java.util.List; -import java.util.stream.Collectors; -public class InetAdressResolver { - - public List getAllByName(String hostname) throws UnknownHostException { - return Arrays.stream(InetAddress.getAllByName(hostname)).map(InetAddress::toString).collect(Collectors.toList()); +class NopMembersResolver implements MembersResolver { + @Override + public List resolveMembers(List membersToResolve) { + return membersToResolve; } } diff --git a/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/TcpIpMembersResolver.java b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/TcpIpMembersResolver.java new file mode 100644 index 00000000000..89e7ef68fc0 --- /dev/null +++ b/server/sonar-process/src/main/java/org/sonar/process/cluster/hz/TcpIpMembersResolver.java @@ -0,0 +1,74 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.process.cluster.hz; + +import com.hazelcast.internal.util.AddressUtil; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; + +import static java.lang.String.format; +import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HZ_PORT; + +class TcpIpMembersResolver implements MembersResolver { + private static final Logger LOG = Loggers.get(TcpIpMembersResolver.class); + + @Override + public List resolveMembers(List membersToResolve) { + return membersToResolve.stream().map(this::extractMembers).flatMap(Collection::stream).collect(Collectors.toList()); + } + + private List extractMembers(String host) { + LOG.debug("Trying to add host: " + host); + String hostStripped = host.split(":")[0]; + if (AddressUtil.isIpAddress(hostStripped)) { + LOG.debug("Found ip based host config for host: " + host); + return Collections.singletonList(host.contains(":") ? host : format("%s:%s", host, CLUSTER_NODE_HZ_PORT.getDefaultValue())); + } else { + List membersToAdd = new ArrayList<>(); + for (String memberIp : getAllByName(hostStripped)) { + String prefix = memberIp.split("/")[1]; + LOG.debug("Found IP for: " + hostStripped + " : " + prefix); + String memberPort = host.contains(":") ? host.split(":")[1] : CLUSTER_NODE_HZ_PORT.getDefaultValue(); + String member = prefix + ":" + memberPort; + membersToAdd.add(member); + } + return membersToAdd; + } + } + + private List getAllByName(String hostname) { + LOG.debug("Trying to resolve Hostname: " + hostname); + try { + return Arrays.stream(InetAddress.getAllByName(hostname)).map(InetAddress::toString).collect(Collectors.toList()); + } catch (UnknownHostException e) { + LOG.error("Host could not be found: " + e.getMessage()); + } + return new ArrayList<>(); + } + +} diff --git a/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberBuilderTest.java b/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberBuilderTest.java index ff730e80f51..054c05cda77 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberBuilderTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberBuilderTest.java @@ -20,58 +20,74 @@ package org.sonar.process.cluster.hz; import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.Arrays; import java.util.Collections; -import java.util.List; -import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.DisableOnDebug; -import org.junit.rules.ExpectedException; import org.junit.rules.TestRule; import org.junit.rules.Timeout; import org.sonar.process.NetworkUtilsImpl; import org.sonar.process.ProcessId; -import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.sonar.process.ProcessProperties.Property.CLUSTER_NODE_HZ_PORT; +import static org.assertj.core.api.Assertions.assertThatThrownBy; public class HazelcastMemberBuilderTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); @Rule public TestRule safeguardTimeout = new DisableOnDebug(Timeout.seconds(60)); // use loopback for support of offline builds private final InetAddress loopback = InetAddress.getLoopbackAddress(); - private final InetAdressResolver inetAdressResolver = mock(InetAdressResolver.class); - private final HazelcastMemberBuilder underTest = new HazelcastMemberBuilder(inetAdressResolver); - - @Before - public void before() throws UnknownHostException { - when(inetAdressResolver.getAllByName("foo")).thenReturn(Collections.singletonList("foo/5.6.7.8")); - when(inetAdressResolver.getAllByName("bar")).thenReturn(Collections.singletonList("bar/8.7.6.5")); - when(inetAdressResolver.getAllByName("wizz")).thenReturn(Arrays.asList("wizz/1.2.3.4", "wizz/2.3.4.5", "wizz/3.4.5.6")); - when(inetAdressResolver.getAllByName("ninja")).thenReturn(Arrays.asList("ninja/4.5.6.7", "ninja/5.6.7.8")); + + @Test + public void build_tcp_ip_member_hostaddress() { + HazelcastMember member = new HazelcastMemberBuilder(JoinConfigurationType.TCP_IP) + .setMembers(Collections.singletonList(loopback.getHostAddress())) + .setProcessId(ProcessId.COMPUTE_ENGINE) + .setNodeName("bar") + .setPort(NetworkUtilsImpl.INSTANCE.getNextLoopbackAvailablePort()) + .setNetworkInterface(loopback.getHostAddress()) + .build(); + + assertThat(member.getUuid()).isNotNull(); + assertThat(member.getClusterTime()).isPositive(); + assertThat(member.getCluster().getMembers()).hasSize(1); + assertThat(member.getMemberUuids()).containsOnlyOnce(member.getUuid()); + + assertThat(member.getAtomicReference("baz")).isNotNull(); + assertThat(member.getLock("baz")).isNotNull(); + assertThat(member.getReplicatedMap("baz")).isNotNull(); + + member.close(); } @Test - public void testMultipleIPsByHostname() { - underTest.setMembers(asList("wizz:9001", "ninja")); + public void build_tcp_ip_member_hostname() { + HazelcastMember member = new HazelcastMemberBuilder(JoinConfigurationType.TCP_IP) + .setMembers(Collections.singletonList(loopback.getHostName())) + .setProcessId(ProcessId.COMPUTE_ENGINE) + .setNodeName("bar") + .setPort(NetworkUtilsImpl.INSTANCE.getNextLoopbackAvailablePort()) + .setNetworkInterface(loopback.getHostAddress()) + .build(); + + assertThat(member.getUuid()).isNotNull(); + assertThat(member.getClusterTime()).isPositive(); + assertThat(member.getCluster().getMembers()).hasSize(1); + assertThat(member.getMemberUuids()).containsOnlyOnce(member.getUuid()); - List members = underTest.getMembers(); - assertThat(members).containsExactlyInAnyOrder("1.2.3.4:9001", "2.3.4.5:9001", "3.4.5.6:9001", "4.5.6.7:9003", "5.6.7.8:9003"); + assertThat(member.getAtomicReference("baz")).isNotNull(); + assertThat(member.getLock("baz")).isNotNull(); + assertThat(member.getReplicatedMap("baz")).isNotNull(); + member.close(); } @Test - public void build_member() { - HazelcastMember member = underTest + public void build_kubernetes_member() { + HazelcastMember member = new HazelcastMemberBuilder(JoinConfigurationType.KUBERNETES) + .setMembers(Collections.singletonList(loopback.getHostAddress())) .setProcessId(ProcessId.COMPUTE_ENGINE) .setNodeName("bar") .setPort(NetworkUtilsImpl.INSTANCE.getNextLoopbackAvailablePort()) @@ -90,21 +106,11 @@ public class HazelcastMemberBuilderTest { member.close(); } - @Test - public void default_port_is_added_when_missing() { - underTest.setMembers(asList("foo", "bar:9100", "1.2.3.4")); - - assertThat(underTest.getMembers()).containsExactly( - "5.6.7.8:" + CLUSTER_NODE_HZ_PORT.getDefaultValue(), - "8.7.6.5:9100", - "1.2.3.4:" + CLUSTER_NODE_HZ_PORT.getDefaultValue()); - } - @Test public void fail_if_elasticsearch_process() { - expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("Hazelcast must not be enabled on Elasticsearch node"); - - underTest.setProcessId(ProcessId.ELASTICSEARCH); + var builder = new HazelcastMemberBuilder(JoinConfigurationType.TCP_IP); + assertThatThrownBy(() -> builder.setProcessId(ProcessId.ELASTICSEARCH)) + .isInstanceOf(IllegalArgumentException.class) + .hasMessage("Hazelcast must not be enabled on Elasticsearch node"); } } diff --git a/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberImplTest.java b/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberImplTest.java index 039ccb3b440..62202667554 100644 --- a/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberImplTest.java +++ b/server/sonar-process/src/test/java/org/sonar/process/cluster/hz/HazelcastMemberImplTest.java @@ -110,7 +110,7 @@ public class HazelcastMemberImplTest { } private static HazelcastMember newHzMember(int port, int... otherPorts) { - return new HazelcastMemberBuilder(new InetAdressResolver()) + return new HazelcastMemberBuilder(JoinConfigurationType.TCP_IP) .setProcessId(ProcessId.COMPUTE_ENGINE) .setNodeName("name" + port) .setPort(port) -- 2.39.5