diff --git a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java index 1136e660453b..c6b5952585e0 100644 --- a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java +++ b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseCluster.java @@ -135,6 +135,26 @@ public interface TestingHBaseCluster { */ List getRegionServerAddresses(); + /** + * Get the web UI address of the active master if there is one. + */ + Optional getActiveMasterInfoAddress(); + + /** + * Get the web UI address of the active NameNode if there is one. + */ + Optional getActiveNameNodeInfoAddress(); + + /** + * Get the 'hbase.zookeeper.quorum' configuration value for the ZooKeeper cluster. + */ + Optional getZooKeeperQuorum(); + + /** + * Get the list of master addresses. + */ + List getMasterAddresses(); + /** * Get the server side {@link Region} interface for the specific region. *

diff --git a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java index 35198e770db0..95f4ffff3ac8 100644 --- a/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java +++ b/hbase-testing-util/src/main/java/org/apache/hadoop/hbase/testing/TestingHBaseClusterImpl.java @@ -17,6 +17,9 @@ */ package org.apache.hadoop.hbase.testing; +import static org.apache.hadoop.hbase.http.ServerConfigurationKeys.HBASE_SSL_ENABLED_KEY; + +import java.net.InetSocketAddress; import java.util.List; import java.util.Optional; import java.util.UUID; @@ -24,6 +27,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.hbase.HBaseTestingUtil; @@ -37,6 +41,9 @@ import org.apache.hadoop.hbase.regionserver.Region; import org.apache.hadoop.hbase.util.JVMClusterUtil.MasterThread; import org.apache.hadoop.hbase.util.JVMClusterUtil.RegionServerThread; +import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster; +import org.apache.hadoop.hdfs.MiniDFSCluster; +import org.apache.hadoop.hdfs.server.namenode.NameNode; import org.apache.yetus.audience.InterfaceAudience; import org.apache.hbase.thirdparty.com.google.common.base.Preconditions; @@ -147,7 +154,7 @@ public void startHBaseCluster() throws Exception { public void start() throws Exception { Preconditions.checkState(!miniClusterRunning, "Cluster has already been started"); if (externalZkConnectString == null) { - util.startMiniZKCluster(); + util.startMiniZKCluster(option.getNumZkServers()); } else { Configuration conf = util.getConfiguration(); conf.set(HConstants.ZOOKEEPER_QUORUM, externalZkConnectString); @@ -219,6 +226,76 @@ public List getRegionServerAddresses() { .map(t -> t.getRegionServer().getServerName()).collect(Collectors.toList()); } + @Override + public Optional getActiveMasterInfoAddress() { + final HMaster master = util.getMiniHBaseCluster().getMaster(); + + // No active master + if (master == null) { + return Optional.empty(); + } + + final Configuration conf = master.getConfiguration(); + final int port = conf.getInt(HConstants.MASTER_INFO_PORT, 0); + + // Web UI disabled + if (port <= 0) { + return Optional.empty(); + } + + final String protocol = conf.getBoolean(HBASE_SSL_ENABLED_KEY, false) ? "https" : "http"; + final String hostname = master.getServerName().getHostname(); + return Optional.of(String.format("%s://%s:%d", protocol, hostname, port)); + } + + @Override + public Optional getActiveNameNodeInfoAddress() { + final MiniDFSCluster cluster = util.getDFSCluster(); + + // External DFS cluster + if (cluster == null) { + return Optional.empty(); + } + + final NameNode ann = Stream.of(cluster.getNameNodeInfos()).map(i -> i.nameNode) + .filter(NameNode::isActiveState).findFirst().orElse(null); + + // No active NameNode + if (ann == null) { + return Optional.empty(); + } + + String protocol = "http"; + InetSocketAddress address = ann.getHttpAddress(); + if (address == null) { + protocol = "https"; + address = ann.getHttpsAddress(); + } + + // Neither HTTP nor HTTPS address is available + if (address == null) { + return Optional.empty(); + } + + return Optional + .of(String.format("%s://%s:%d", protocol, address.getHostName(), address.getPort())); + } + + @Override + public Optional getZooKeeperQuorum() { + return Optional.ofNullable(util.getZkCluster()) + .map(zk -> zk.getClientPortList().stream() + .map(port -> String.format("%s:%d", MiniZooKeeperCluster.HOST, port)) + .collect(Collectors.joining(","))); + } + + @Override + public List getMasterAddresses() { + return util.getMiniHBaseCluster().getMasterThreads().stream() + .map(mt -> mt.getMaster().getServerName()).map(sn -> sn.getHostname() + ':' + sn.getPort()) + .collect(Collectors.toList()); + } + @Override public Optional getRegion(RegionInfo regionInfo) { for (RegionServerThread t : util.getMiniHBaseCluster().getRegionServerThreads()) { diff --git a/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java b/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java index 874e7562a23f..e4a5083cb86b 100644 --- a/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java +++ b/hbase-testing-util/src/test/java/org/apache/hadoop/hbase/testing/TestTestingHBaseCluster.java @@ -23,7 +23,13 @@ import static org.junit.Assert.assertTrue; import java.util.Collection; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Stream; +import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.HBaseConfiguration; +import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.Waiter; import org.apache.hadoop.hbase.client.Admin; @@ -59,8 +65,10 @@ public class TestTestingHBaseCluster { @BeforeClass public static void setUpBeforeClass() throws Exception { + final Configuration conf = HBaseConfiguration.create(); + conf.setInt(HConstants.MASTER_INFO_PORT, 0); CLUSTER = TestingHBaseCluster.create(TestingHBaseClusterOption.builder().numMasters(2) - .numRegionServers(3).numDataNodes(3).build()); + .numZkServers(3).numRegionServers(3).numDataNodes(3).conf(conf).build()); } @AfterClass @@ -150,5 +158,22 @@ public void testGetAddresses() throws Exception { assertTrue(CLUSTER.getActiveMasterAddress().isPresent()); assertEquals(1, CLUSTER.getBackupMasterAddresses().size()); assertEquals(3, CLUSTER.getRegionServerAddresses().size()); + + // [HOSTNAME1:PORT1, HOSTNAME2:PORT2] + final List masterAddrs = CLUSTER.getMasterAddresses(); + assertEquals(2, masterAddrs.size()); + assertTrue(masterAddrs.stream().allMatch(addr -> addr.matches(".*:[0-9]+$"))); + + // ZooKeeper quorum: localhost:PORT1,localhost:PORT2,localhost:PORT3 + final String[] quorum = CLUSTER.getZooKeeperQuorum().orElse("").split(","); + assertEquals(3, quorum.length); + assertTrue(Stream.of(quorum).allMatch(a -> Pattern.matches(".*:[0-9]+$", a))); + + // Web UI addresses + final String addressPattern = "^https?://.*:[0-9]+$"; + assertTrue(CLUSTER.getActiveMasterInfoAddress().map(a -> Pattern.matches(addressPattern, a)) + .orElse(false)); + assertTrue(CLUSTER.getActiveNameNodeInfoAddress().map(a -> Pattern.matches(addressPattern, a)) + .orElse(false)); } }